If I understand correctly, this is the example scenario:
- listOne [datab] items:
[A, B, C, D] - listTwo [front] items:
[B, C, D, E, F]
and what you need to get as an effect is:
- added:
[E, F] - deleted:
[A]
First thing first, I would use some type adapter or extend the different types from one common class and override the equals method so you can match them by id and name
Secondly, this is very easy operations on sets (you could use set's but list are fine too). I recommend using a library: https://commons.apache.org/proper/commons-collections/apidocs/org/apache/commons/collections4/CollectionUtils.html
And now basically:
- added is
listTwo - listOne - deleted is
listOne - listTwo
and using java code:
- added:
CollectionUtils.removeAll(listTwo, listOne) - deleted:
CollectionUtils.removeAll(listOne, listTwo)
Otherwise, all collections implementing Collection (Java Docs) also has removeAll method, which you can use.
If I understand correctly, this is the example scenario:
- listOne [datab] items:
[A, B, C, D] - listTwo [front] items:
[B, C, D, E, F]
and what you need to get as an effect is:
- added:
[E, F] - deleted:
[A]
First thing first, I would use some type adapter or extend the different types from one common class and override the equals method so you can match them by id and name
Secondly, this is very easy operations on sets (you could use set's but list are fine too). I recommend using a library: https://commons.apache.org/proper/commons-collections/apidocs/org/apache/commons/collections4/CollectionUtils.html
And now basically:
- added is
listTwo - listOne - deleted is
listOne - listTwo
and using java code:
- added:
CollectionUtils.removeAll(listTwo, listOne) - deleted:
CollectionUtils.removeAll(listOne, listTwo)
Otherwise, all collections implementing Collection (Java Docs) also has removeAll method, which you can use.
I propose solution using java 8 streams:
ArrayList<ObjOne> list = new ArrayList<>(Arrays.asList(new ObjOne("1","1"),new ObjOne("3","3"),new ObjOne("2","2")));
ArrayList<ObjTwo> list2 = new ArrayList<>(Arrays.asList(new ObjTwo("1","1"),new ObjTwo("3","3"),new ObjTwo("4","4")));
List<ObjOne> removed = list.stream().filter(o1 -> list2.stream().noneMatch(o2 -> o2.getId().equals(o1.getId())))
.collect(Collectors.toList());
System.out.print("added ");
removed.forEach(System.out::println);
List<ObjTwo> added = list2.stream().filter(o1 -> list.stream().noneMatch(o2 -> o2.getId().equals(o1.getId())))
.collect(Collectors.toList());
System.out.print("removed ");
added.forEach(System.out::println);
This is basically your solution but implemented using streams, which will make your code shorter and easer to read
An elegant way to find diff of two list of objects in Java - Code Review Stack Exchange
java - How can I return the difference between two lists? - Stack Overflow
Java Compare Two List's object values? - Stack Overflow
Java Compare Two Lists - Stack Overflow
I would create this method:
private MyObject findMatch(List<MyObject> objsFromDB, MyObjRequest req_obj){
for(MyObject db_obj : objsFromDB){
if(isSameObj(db_obj, req_obj)){
return db_obj;
}
}
return null;
}
and refactor accordingly.
Beyond that the only suggestion I would have is perhaps some better variable names (at least use a single naming style; if you don't already have one, use this: http://www.oracle.com/technetwork/java/codeconventions-135099.html#367).
My suggestion would be to move the isSameObj inside the MyObject class as it deals with the attributes inside that object. You can override the equals method of MyObject so that the equals method in MyObject will be like
boolean equals(MyObject target){
return this.getMatch().equals(target.getMatch());
}
and the original code will become like
if(db_obj.equals(req_obj)) instead of if(isSameObj(db_obj, req_obj))
You can convert them to Set collections, and perform a set difference operation on them.
Like this:
Set<Date> ad = new HashSet<Date>(a);
Set<Date> bd = new HashSet<Date>(b);
ad.removeAll(bd);
If you only want find missing values in b, you can do:
List toReturn = new ArrayList(a);
toReturn.removeAll(b);
return toReturn;
If you want to find out values which are present in either list you can execute upper code twice. With changed lists.
It's not the most efficient solution but the most terse code would be:
boolean equalLists = listA.size() == listB.size() && listA.containsAll(listB);
Update:
@WesleyPorter is right. The solution above will not work if duplicate objects are in the collection.
For a complete solution you need to iterate over a collection so duplicate objects are handled correctly.
private static boolean cmp( List<?> l1, List<?> l2 ) {
// make a copy of the list so the original list is not changed, and remove() is supported
ArrayList<?> cp = new ArrayList<>( l1 );
for ( Object o : l2 ) {
if ( !cp.remove( o ) ) {
return false;
}
}
return cp.isEmpty();
}
Update 28-Oct-2014:
@RoeeGavriel is right. The return statement needs to be conditional. The code above is updated.
ArrayList already have support for this, with the equals method. Quoting the docs
... In other words, two lists are defined to be equal if they contain the same elements in the same order.
It does require you to properly implement equals in your MyData class.
Edit
You have updated the question stating that the lists could have different orders. In that case, sort your list first, and then apply equals.
EDIT
Here are two versions. One using ArrayList and other using HashSet
Compare them and create your own version from this, until you get what you need.
This should be enough to cover the:
P.S: It is not a school assignment :) So if you just guide me it will be enough
part of your question.
continuing with the original answer:
You may use a java.util.Collection and/or java.util.ArrayList for that.
The retainAll method does the following:
Retains only the elements in this collection that are contained in the specified collection
see this sample:
import java.util.Collection;
import java.util.ArrayList;
import java.util.Arrays;
public class Repeated {
public static void main( String [] args ) {
Collection listOne = new ArrayList(Arrays.asList("milan","dingo", "elpha", "hafil", "meat", "iga", "neeta.peeta"));
Collection listTwo = new ArrayList(Arrays.asList("hafil", "iga", "binga", "mike", "dingo"));
listOne.retainAll( listTwo );
System.out.println( listOne );
}
}
EDIT
For the second part ( similar values ) you may use the removeAll method:
Removes all of this collection's elements that are also contained in the specified collection.
This second version gives you also the similar values and handles repeated ( by discarding them).
This time the Collection could be a Set instead of a List ( the difference is, the Set doesn't allow repeated values )
import java.util.Collection;
import java.util.HashSet;
import java.util.Arrays;
class Repeated {
public static void main( String [] args ) {
Collection<String> listOne = Arrays.asList("milan","iga",
"dingo","iga",
"elpha","iga",
"hafil","iga",
"meat","iga",
"neeta.peeta","iga");
Collection<String> listTwo = Arrays.asList("hafil",
"iga",
"binga",
"mike",
"dingo","dingo","dingo");
Collection<String> similar = new HashSet<String>( listOne );
Collection<String> different = new HashSet<String>();
different.addAll( listOne );
different.addAll( listTwo );
similar.retainAll( listTwo );
different.removeAll( similar );
System.out.printf("One:%s%nTwo:%s%nSimilar:%s%nDifferent:%s%n", listOne, listTwo, similar, different);
}
}
Output:
$ java Repeated
One:[milan, iga, dingo, iga, elpha, iga, hafil, iga, meat, iga, neeta.peeta, iga]
Two:[hafil, iga, binga, mike, dingo, dingo, dingo]
Similar:[dingo, iga, hafil]
Different:[mike, binga, milan, meat, elpha, neeta.peeta]
If it doesn't do exactly what you need, it gives you a good start so you can handle from here.
Question for the reader: How would you include all the repeated values?
You can try intersection() and subtract() methods from CollectionUtils.
intersection() method gives you a collection containing common elements and the subtract() method gives you all the uncommon ones.
They should also take care of similar elements
I want to do a certain action each time an object is the same and at the same index and another action each time an object is present in both lists but not at the same index. It has to match though (i cant do the second action 4 times if both lists are like that ex :(r,f,f,f,f) (r, r, r, r, r) only once