Duplicates in arraylist not to be printed - java

I have an arraylist with bankcustomers. Some customers occur more than once (this happens if they have more than one account).
Now I want to print all the customers, but if then occur more than once I only want to print them once.
Heres is my non working code. As it is now it prints the whole list. How can I add code to only print duplicates once?
public void showCustomers() {
private ArrayList<Customer> customers = new ArrayList<Customer>();
for(Customer c: customers) {
System.out.println("First name: " + c.getFirstname());
System.out.println("Last name: " + c.getLastname());
System.out.println("Customer number: " + c.getNumber());
for(Account a : c.getAccounts()) {
System.out.println("Account number: " + a.getAccountId());
}
}
}
I prefer not to use HashSet (if it's not neccesary). I'm trying to learn ArrayLists now.

Add all your elements to a Set:
for (Customer c: new HashSet<Customer>(customers)) {
From the linked Javadoc:
A collection that contains no duplicate element

Whenever you need need to avoid duplicates, think Set
List<String> lst = Arrays.asList("Foo", "Foo", "Bar", "Baz");
for(String s : new HashSet<>(lst)) {
System.out.println(s);
}

If the Customer class already implements hashCode and equals in the way you expect it you can just use a Set.
Set<Customer> uniqueCustomers = new HashSet<Customer>(customers);
if you need to keep the original order of the elements in the List use a LinkedHashSet
Set<Customer> uniqueOrderedCustomers = new LinkedHashSet<Customer>(customers);
if the Customer class does not implement hashCode and equals or you can't implement it, because you don't have the sources, use a TreeSet and implement a Comparator.

Optimally, you'll want to create a parallel array within the showCustomers() method.
Have the array contain a relative boolean value.
Within the for(Customer c: customers) iteration create (nest) a conditional statement (an if, else).
From within the conditional, acquire the value at the nth index of the parallel array.
If the current value is false set it to true and print out to the console.
If the current value is true, then call the continue statement to have the iteration go to the next item (and not print to the console).
The following will print the first Customer of the duplicate or multiple entries:
public void showCustomers() {
// Visibility of variables in class methods is irrelevant
// All variables/values created within a method will only be
// accessible from within it's scope
/*private*/ ArrayList<Customer> customers = new ArrayList<Customer>();
// Create a parallel list
List<Boolean> customers_b = new ArrayList<Boolean>(customers.size());
// Use this value to hold the index of your current item
int n = 0;
for(Customer c: customers) {
if(customers_b.get(n) == false)
{
System.out.println("First name: " + c.getFirstname());
System.out.println("Last name: " + c.getFirstname());
System.out.println("Customer number: " + c.getNumber());
for(Account a : c.getAccounts()) {
System.out.println("Account number: " + a.getAccountId());
}
customers_b.set(n, true);
n++;
}
else
{
n++;
continue;
}
}
}

convert your list into a Hashset and this will do the trick, since hashsets doesn't allow duplicate values to be stored but in case of HashMap and if there's a duplicate, it replaces the old value with the new one.

Related

How to print map with list as value, which grows as every list element will have their own values and furthermore? (Java)

The issue is that I must add a for-loop as my tree grows. So, the basic idea is that I have a tree which has branches, and those branches could have more branches as it grows in the application. The issue is that as the branch grows, I have to add more for loop.
Tree Strut
So, if you see Gen1 have three branches GenTest1, GenTest2, GenTest3. Later GenTest1 have two more branches 321 and MAT00000000000630, further GenTest2 have branch 123 and 123 also have 21 as a branch.
So, this grows more the branches more the for loop.
Implementation
The idea of how I am implementing
parent = new Map<String,List<String>>;
for (Map.Entry i : parent.entrySet()) {
key = i.getKey();
valueList = (List<String>) i.getValue();
S.O.P("Key: "+
key +
" & Value: " +
valueList);
for (String child: valueList)
{
parent = Map(child.get(0)) //Please don't worry about how the string value is converted into Map I did with my helper classes.
for(Map.Entry j : parent.entrySet())
{
key = j.getKey();
valueList = (List<String>) j.getValue();
S.O.P("2ndKey: "+
key +
" & 2ndValue: " +
valueList);
}
}
}
You see I can retrieve the branch of GenTest1 and GenTest2.
But in GenTest2 there is 123 and for 123 I must use for loop again.
I know recursion is the best option but, I am having a problem achieving it.
Ok the output should be like this
Gen1
GenTest1
321
MAT000000000628
GenTest2
123
21
GenTest3
maybe you need some like this...
private void print(Map<String, List<String>> parent) {
for (Map.Entry<String, List<String>> i : parent.entrySet()) {
String key = i.getKey();
List<String> valueList = i.getValue();
System.out.println("Key: " +
key +
" & Value: " +
valueList);
for (String child : valueList) {
print(Map(child.get(0))); // you helped method
}
}
}
In the Java, there is a standard TreeNode interface that you should consider implementing within WTPart. Its main methods are
n.children() // equivalent to your MBOMH.getPCP(MBOMH.getPP(n).get(0))
n.isLeaf() // MISSING in your code, to know when to stop digging
n.getParent() // this you do not need for your specific case
For a tree of MyNode extends TreeNode are used, you can print contents recursively by implementing a print function in MyNode, as follows:
public void print() {
System.out.println(this); // calls toString() to print self
if (isLeaf()) {
return; // avoids trying to print children if none there
}
// TreeNode's children() returns an enumeration; returning a List
// would make it easier to iterate with for (MyNode n : children())
for (Enumeration<MyNode> e=children(); e.hasNextElement(); /**/) {
e.next().print();
}
}
So my suggestion is to implement an isLeaf(), and while you are at it, implement a children() method that is less ugly than MechatronicBOMHelper.getPartentChildPart(MechatronicBOMHelper.getPartProp(child).get(0)). Since you have a helper class, you can consider having a MechatronicBOMHelper.childrenOf(child) instead of having a child.getChildren(), but the second is more OO-like.
It was simple recursion which I made complex through iteration.
Map<String, List<String>> parent;
for (Map.Entry<String, List<String>> i : root.entrySet()) {
logger.debug("Root"+" "+i.getKey());
for (String j : i.getValue()) {
parent = Map(j.get(0)); // using my helper class
build(parent);

Find match element in array

completely new to Java, I am trying to find the matched element from one array into another, cannot seem to understand how to do it. Here is a sample of how the data is and how far I've gotten:
In this code and after printing this line, this is how the data is:
ArrayList<String> all_accounts = new ArrayList<String>();
all_accounts.add(acc);
System.out.println("\nArray 1:" + all_accounts);
Result Array 1:
Array 1:[77737320]
Array 1:[88405378]
Array 1:[00056893]
Array 1:[10709816]
ArrayList<String> cancel_accounts = new ArrayList<String>();
cancel_accounts.add(cancel_acc);
System.out.println("\nArray 2:" + cancel_accounts);
Results from Array 2:
Array 2:[77737320]
Array 2:[]
Array 2:[]
Array 2:[]
Stack here, I still cant understand why it doesn't match:
String found = null;
for (String account: all_accounts) {
for (String canceled: cancel_accounts) {
System.out.println(canceled);
found = canceled;
}
System.out.println(found);
if(account.equals(found) ) {
System.out.println(account);
}
}
I need to find the matched element, 77737320 in this case.
Thanks for looking!
+1 for answer from user6904265
However, You need not create a new HashSet. You can use ArrayList.retainAll(). If you want to maintain the all_accounts list, create a new clone and use that instead.
You could implement this as intersection between sets:
Set<String> set_all_account = new HashSet<String>(all_accounts);
Set<String> set_cancel_accounts = new HashSet<String>(cancel_accounts);
set_all_account.retainAll(set_cancel_accounts);
set_all_account.forEach(x -> System.out.println("Element matched: "+x));
Or as said by kartiks in his comment you could call the retainAll method directly on the all_accounts array:
all_accounts.retainAll(cancel_accounts);
all_accounts.forEach(x -> System.out.println("matched element: "+x));
Pay attention with this solution because in this case retainAll applies directly on the ArrayList and modifies it (as you can see the final result is in the all_accounts array). Moreover duplicate elements remain in the result array.
Last implementation (if you want compute intersection and print the result all in one line, also this version keeps duplicate elements):
all_accounts.stream().filter(x -> cancel_accounts.contains(x)).forEach(x -> System.out.println("matched element: "+x));
You can loop through the one list and search the second list for each element in first.
for (String account: all_accounts) {
if (cancel_accounts.contains(account) {
// Match found - do something....
System.out.println(account);
}
}
Just add an equals check to your for - loops (will work even without List#contains method)
for(String account: all_accounts) {
System.out.println(account);
for(String canceled: cancel_accounts){
System.out.println(canceled);
if(account.equals(cancelled)){
//you've found first intersection, cancelled exists in both
System.out.println(canceled + " is the same as " + account);
}
}
}

Array List Iterator

I am looking to remove the element from an array list, the user has to input the element to be removed. At the moment my Iterator seems to be wrong. User inputs the Car Model, Color, ID Plate, Number of doors. User has to input the id and it should delete the whole element
Brand is :Nissan Color is Black ID is LS57GHT Door is 4 (this should be all deleted when user inputs the correct ID).
This is what I am using :
ArrayList<String> List;
List = new ArrayList<>(maxCapacity);
for (Iterator<String> iterator = List.iterator(); iterator.hasNext();) {
String id = input.next();
if (List.equals(id)) {
iterator.remove();
}
}
You actually need to get the current element of the iterator by calling
String current = iterator.next();
inside your loop.
You are prompting the user to enter a number (assuming your input is actually a Scanner that you declared somewhere earlier) in every iteration of your loop. You should move that call out of the loop.
You want to compare the currently iterated element (see 1.) to the ID entered by the user. At the moment you are comparing your entire ArrayList object to the ID string, which will always be false.
Change your code as in example:
public static void main(String[] args) {
List<String> list = new ArrayList<>(Arrays.asList("a", "b", "c"));
System.out.println("Input ID you want remove: ");
Scanner scanner = new Scanner(System.in);
String inputId = scanner.nextLine();
System.out.println("List before removing: " + list);
for (Iterator<String> iterator = list.iterator(); iterator.hasNext(); ) {
String id = iterator.next();
if (id.equals(inputId)) {
iterator.remove();
break;
}
}
System.out.println("List after removing: " + list);
}
You'll get the following output:
Input ID you want remove:
a
List before removing: [a, b, c]
List after removing: [b, c]
Example can be reproduced here.
And never use a capital letters to name your variables, it makes code unreadable and sometimes confusing. In your case ArrayList named List looks like java.util.List interface.

Pairing among the members in same list in java

In problem statement, I have 'n' number of families with 'n' number of family members.
eg:
John jane (family 1)
tiya (family 2)
Erika (family 3)
I have to assign all members in such a way that person should not pair with the his family member.
and output should be:
John => tiya
jane => Erika
tiya => jane
Erika => john
I have created the object Person(name ,familyID, isAllocated).
Created the list and added personName_id in this this.
I am thinking to use the map for association. So that john_1 will be key and tiya_2 will be value.
I am failing to associate those pairs through map. How can I shuffle the members it the list.
Also, It would be nice if anyone could suggest me the better solution.
Code:
Getting person:
public static List getperson()
{
Scanner keyboard = new Scanner(System.in);
String line = null;
int count = 0;
List <Person> people = new ArrayList<>();
while(!(line = keyboard.nextLine()).isEmpty()) {
String[] values = line.split("\\s+");
//System.out.print("entered: " + Arrays.toString(values) + "\n");
int familyid = count++;
for(String name :values)
{
Person person = new Person();
person.setFamilyId(familyid);
person.setName(name);
person.setAllocated(false);
people.add(person);
}
}
return people;
}
Mapping:
public static List mapGifts(List pesonList)
{
Map<String , String> personMap = new HashMap<String , String>();
Iterator<Person> itr = pesonList.iterator();
Iterator<Person> itr2 = pesonList.iterator();
List<String> sender = new ArrayList<>();
while(itr.hasNext())
{
Person p = itr.next();
sender.add(p.getName()+"_"+p.getFamilyId());
personMap.put(p.getName()+"_"+p.getFamilyId(), "");
// p.setAllocated(true);
}
while(itr2.hasNext())
{
/*if(p.isAllocated())
{*/
// Separate Sender name and id from sender list
//check this id match with new p1.getFamilyId()
for(String sendername :sender)
{
// System.out.println("Sender "+sendername);
personMap.put(sendername, "");
String[] names = sendername.split("_");
String part1 = names[0]; // 004
String familyId = names[1]; // 004
Person p2 = itr2.next();
System.out.println(p2.getFamilyId() +" "+familyId +" "+p2.isAllocated());
if(p2.isAllocated())
{
for ( String value: personMap.values()) {
if ( value != sendername) {
}
}
}
if( p2.getFamilyId() != Integer.parseInt(familyId))
{
// add values in map
}
}
break;
// Person newPerson = personLists.get(j);
}
for (Iterator it = personMap.entrySet().iterator(); it.hasNext();)
{
Map.Entry entry = (Map.Entry) it.next();
Object key = entry.getKey();
Object value = entry.getValue();
System.out.println("Gifts "+key+"=>"+value);
}
return pesonList;
}
Thanks
From what I've read, you only care that you match people. How they match doesn't matter. That said, I'll assume you have a list of FamilyID's, and a list of names of everyone, and that you can sort the list of people according to family IDs.
Let's call them:
List<FamilyID> families; and
LinkedList<Person> people;, respectively. (You can make FamilyID an enumerated class)
We need two hashmaps. One to generate a list (essentially an adjacency list) of family members given a familyID:
HashMap<FamilyID, List<Person>> familyMembers; ,
and one to generate a list of sender(key) and receiver(value) pairs:
HashMap<Person, Person> pairs;
A useful function may be that, when given a person and their family ID, we can find the next available person who can receive from them.
String generateReceiver(Person newSender, FamilyID familyID);
Implementation of this method should be pretty straightforward. You can iterate through the list of people and check to see if the current person is not a family member. If that condition passes, you remove them from the "people" list so you don't try to iterate through them again. If you're using a linked list for this, removal is O(1) since you'll already have the reference. Worst case on traversals the list is n + n - 1 + ... + 2 times to get O(n^2) time efficiency (i.e. you have one large family and many small ones). Work around that would be to ditch the LinkedList, use an Array-based list, and keep a separate array of index values corresponding to each "currently available receiver of a specified family". You'd initialize these values as you added the people from each family to the people list (i.e. start of family 1 is index "0"; if family 1 has 2 people, start of family 2 would be index "2"). This would make the function O(1) time if you just incremented the current available receiver index everytime you added a sender-receiver pair. (Message me if you want more details on this!)
Last but not least, the loop is doing this for all people.
for (List<Person> family : familyMembers)
for (Person person : family)
{
// get the next available receiver who is not a family member
// add the family member and its receiver to "pairs" hash
}
Note that the above loop is pseudocode. If you're wondering if you would generate conflicting receiver/senders with this method, you won't. The list of people is essentially acting as a list of receivers. Whichever way you implement the people list, the generateReceiver(...)eliminates the chance that the algorithm would see a faulty-receiver. Per efficiency, if you do the array based implementation then you're at O(N) time for generating all pair values, where N is the total number of people. The program itself would be O(N) space as well.
Of course, this is all based on the assumption you have enough people to match for sender-receiver pairs. You'd need to add bells and whistles to check for special cases.
Hope this helps! Good luck!

ArrayList of string arrays and iteration, adding, updating or removing values

Start my questions by showing my problem in a code to save time reading.
issues:
-Can't save string[] with 3 values in an ArrayList properly.
-Can't change the value of an array in a ArrayList.
List<String> objects= new ArrayList<String>();
//creates an object to be saved in an arrayList which it will be printed to a file.
custFile(long ID, int acc, String trans)
{
String customer = bank.infoCustomer(iD);
String account = Integer.toString(acc); //bank.infoAccount(iD, acc);
String transactions;
if(trans == "")
{
transactions = "\nNo transactions made\n";
}
else transactions ="\nTransactions : " + trans;
//My string array with three values.
String[] obj = {customer, account, transactions};
if(!objects.isEmpty())
{
int n = objects.size();
int p = 0;
for(int i = 0; i < objects.subList(p, n).size(); i++)
{
if(!objects.listIterator(i).equals(obj))
{
objects.addAll(Arrays.asList(obj));
return; //needed?
}
else
{
//Remove in order to update
objects.remove(i);
//Add to the List
objects.addAll(Arrays.asList(obj));
}
}
else
//Add String[] the first time and only time.
objects.addAll(Arrays.asList(obj));
When I remove a string (with the three values) from the ArrayList, two weird couple of lines containing the third value of the string are left behind:
//This
0
//And this
Transactions : null
I've tried different methods to add and remove and iterate over the ArrayList but nothing seems to work.
Adding: repeats the string value.
Removing: works half the way.
Iterating: won't give me the exact element to be compared or removed.
My String[] obj = {customer, account, transactions}; once I print it looks like this:
//Customer
3 : c
//Account(s)
Account Type:
Saving Account 1005
Balance: 0.0
Account Type:
Credit Account 1006
Balance: 0.0
//Transactions
0
Transactions : null
And the ArrayList contains many strings with similar values(three: customer, account, transactions)
It should be possible to update the objects using this method I believe.
Little push I'll be grateful.
Your description is not very clear. What I can tell you is that if you're iterating over an arraylist it's difficult to remove items mid-loop.
ex) if i = 2 and you remove the 2nd element in the arraylist, your 3rd element is now referenced by 2, but your for loop counter will increment to 3 before checking the arraylist again
As an aside: Object.equals is not implemented, and so when you call object.equals, you're just checking to see that they are the SAME object. In other words, you're comparing the two pointers
Although I did not fix the problem above I found an interesting short cut to my goal. This is how I manage:
Instead of having a string array with three values(customer, account, transactions) I created a string with one value. The class account Saving and class account Credit has access to transaction method from class Account where Saving and Credit inherit. The bank logic responsible for the objects has a method where customer is fetched with all its values coming from a Map; Map < Account, Customer> customerInfo = new HashMap < Account, Customer>(); . In other words here is the seudo:
add transactions to account.
add account to customer.
add customer to list.
Here is my new custFile method.
//List array with string values.
List objects= new ArrayList();
//------------------------------------------------------------------------------------------------
// Description: A method that creates and updates a list Array. The update works by choosing the first
// characters of the input and the existing string in the list and comparing them
// removing if equals and adding the last input containing the new values for the
// string. Adding a new string object otherwise.
// Arguments: Long for Id customer to be created or updated in the list.
// Return: An array list with the current database.
//------------------------------------------------------------------------------------------------
public void custFile(long iD) //, int acc, String trans )
{
String customer = bank.infoCustomer(iD);
System.out.println("\n\n\n" + " String with three values" + "\n\n\n");
System.out.println(customer + "");
System.out.println("\n\n" + " End" + "\n\n");
if(!objects.isEmpty())
{
System.out.println("\n4");
boolean exist= false;
String custToRem = null;
for(int i = 0; i< objects.size(); i++)
{
//A few prints to make sure the values are equals.
System.out.println("1\n");
System.out.println("1a\n");
System.out.println(objects.get(i).substring(0, 5));
System.out.println("1b\n");
System.out.println(customer.substring(0, 5));
System.out.println("1c\n");
if(objects.get(i).substring(0,5).equals(customer.substring(0, 5))) //&& objects.get(i).substring(1, 20).equals(customer.substring(1, 20)))
{
System.out.println("2 Deleting");
custToRem = objects.get(i);
System.out.println(custToRem);
System.out.println("3 Deleted");
exist = true;
}
else
exist = false;
}
if(exist = true)
{
System.out.println("4");
System.out.println(custToRem);
objects.remove(custToRem);
objects.add(customer);
System.out.println("5");
}
else
{
System.out.println("6");
objects.add(custToRem);
System.out.println("7");
}
System.out.println(objects.toString());
}
else
objects.add(customer);
}
//------------------------------------------------------------------------------------------------
// Description: A method that removes a value from the list Array. This by searching throughout the
// list for an identical value.
// Arguments: Long for Id customer to be remove from the list array.
// Return: None.
//------------------------------------------------------------------------------------------------
public void removeObj(long iD)
{
String obj = String.valueOf(iD);
System.out.println("remove fr GUI, iD: " + obj);
String customer = bank.infoCustomer(iD);
Iterator<String> itr = objects.iterator();
String element = "";
while(itr.hasNext())
{
element = (String) itr.next();
if(element.contains(customer))
{
itr.remove();
System.out.println("\n\nitr removed, from removeObj() -GUI ");
break;
}
}
}

Categories