remove one Collection elements from other - java

Hi i have two Collection of SomeType a1,a2 and want to remove all the elements of a2 from a1.
Please suggestion which type of Collection i need to use :
ArrayList
LinkList
some other ?.
Is there any library for this ?

Thanks to all.
After reading your response i created a Filter class like this :
public class Filter {
public <T> Set<T> filter(Set<T> all, Set<T> blocked) {
for (T t : all) {
if(blocked.contains(t)) {
all.remove(t);
}
}
return all;
}
}

Use the collection method Collection.removeAll(Collection<?> c);

Well, you can use a1.removeAll(a2), but the removal would be more efficient if your Collections are HashSet (since the search for an element in a HashSet takes O(1), while in Lists it takes O(n)). Whether you can use HashSet depends on whether a1 and a2 can contain duplicate elements.

To remove from a collection you need to have objects(in your case SomeType) that override equals and hashCode.
Then you don't need a library, just use the removeAll method
Collection<SomeType> a1 = new ArrayList<SomeType>();
Collection<SomeType> a2 = new ArrayList<SomeType>();
a1.removeAll(a2);

Related

Check for duplicate in an ArrayList [duplicate]

I am novice to java. I have an ArrayList and I want to avoid duplicates on insertion. My ArrayList is
ArrayList<kar> karList = new ArrayList<kar>();
and the the field I want to check is :
kar.getinsertkar().
I have read that I can use HashSet or HashMap but I have no clue.
Whenever you want to prevent duplicates, you want to use a Set.
In this case, a HashSet would be just fine for you.
HashSet karSet = new HashSet();
karSet.add(foo);
karSet.add(bar);
karSet.add(foo);
System.out.println(karSet.size());
//Output is 2
For completeness, I would also suggest you use the generic (parameterized) version of the class, assuming Java 5 or higher.
HashSet<String> stringSet = new HashSet<String>();
HashSet<Integer> intSet = new HashSet<Integer>();
...etc...
This will give you some type safety as well for getting items in and out of your set.
A set is simply a collection that can contain no duplicates so it sounds perfect for you.
It is also very simple to implement. For example:
Set<String> mySet = new HashSet<String>();
This would provide you a set that can hold Objects of type String.
To add to the set is just as simple:
mySet.add("My first entry!");
By definition of a set, you can add whatever you want and never run into a duplicate.
Have fun!
EDIT : If you decide you are dead-set on using an ArrayList, it is simple to see if an object is already in the list before adding it. For example:
public void addToList(String newEntry){
if(!myList.contains(newEntry))
myList.add(newEntry);
}
Note: All my examples assume you are using String objects but they can easily be swapped to any other Object type.
Use a HashSet instead of an ArrayList. But, to really make the HashSet really work well, you must override the equals() and hashCode() methods of the class/objects that are inserted into the HashSet.
Foe example:
Set<MyObject> set = new HashSet<MyObject>();
set.add(foo);
set.add(bar);
public class MyObject {
#Override
public boolean equals(Object obj) {
if (obj instanceof MyObject)
return (this.id = obj.id)
else
return false;
}
// now override hashCode()
}
Please see the following documentation for overriding hashCode() and equals().
You can use LinkedHashSet, to avoid duplicated elements and keep the insertion order.
http://docs.oracle.com/javase/7/docs/api/java/util/LinkedHashSet.html
You need to use any Set implementation, e.g you can use HashSet.
If you want to add custom object kar into your HashSet, you need to override equals and hashcode method.
You can read more about equals and hashcode, see
You can implement own List which extends LinkedList and override its add methods:
public boolean add(E e)
public void add(int index, E element)
public boolean addAll(Collection collection)
public boolean addAll(int index, Collection collection)
An example removing repeated Strings in an ArrayList:
var list = new ArrayList<>(List.of(
"hello",
"java",
"test",
"hello"
));
System.out.println(list);
System.out.println(new ArrayList<>(new HashSet<>(list)));
Output:
[hello, java, test, hello]
[java, test, hello]

How to get array of an specific attribute values from a list of custom object

I have a List<MyClass> and there is an attribute named attribute1 in MyClass.
Now the question is, how i can get the attribute1 values from List<MyClass> as an array without looping through the list in traditional way?
You can use Guava's FluentIterable to collect your elements, here's an example assuming attribute1 is an Integer
//populated
List<MyClass> yourList;
List<Integer> listbyAttribute = FluentIterable.from(yourList)
.transform(new Function<MyClass, Integer>() {
public Integer apply(MyClass f) {
return f.getAttribute1();
}
}).toList();
More fun with this Guava class: here
You can create your own class which implements LIST interface. YOu should basically do the implementation which is exactly the same as one of the other implementation of list except;
1)you in your add method, every time you add a new element, append it in a string array which is a variable of your class.
2)and add an extra method, lets say giveMyAttribute1List and return the variable list I mentioned earlier.
you you basically have your answer.
List<MyClass> a = new myListIMpl<MyClass>();
a.giveMyAttribute1List();
If this is some kind of tricky question where you (yourself) are not allowed to use a for-each, an iterator nor an old fashioned for-loop (like being asked in a job interview), I would suggest using the following:
Collections.sort(myList, myComparator)
and create the comparator
public class MyClassComparator implements Comparator<MyClass> {
#Override
public int compare(final MyClass o1, final MyClass o2) {
// implement
}
}
and implement the compare method in such a way, that the attribute1 is either in front (or back, or somewhere you know). Then you can easily fetch the element from the list without manually looping through it.
But this answer applies only if this is some kind of "job interview question", otherwise looping through the list is most likely the only option you have.
If you want to get the value of an attribute of each element in a List, you have to visit each element of that List. In other words, you have to iterate over each element. Whether you visit the elements in order with a loop or randomly in some ridiculous way, you're looping/iterating.
What you are asking for is not possible.

Object without any content/empty Object

while developing I was trying to return an empty List.
public Collection<?> getElements() {
// return elements
}
I searched for an easy way, my first idea was to create for example an ArrayList without any elements and return it. Like the following example:
public Collection<?> getElements() {
return new ArrayList<?>();
}
For me it is too much overhead for an empty list.
There is a really simple solution for the above described "problem":
public Collection<?> getElements() {
return Collections.EMPTY_LIST;
}
That returns an empty list.
Notice:
It returns an immutable object! You can use it only, if you need an object, which isn't editable.
Type-safety
In the case you want to get a type-safe list you should use the following example [1]:
List<String> s = Collections.emptyList();
Three kinds of interfaces are supported:
List:
List l = Collections.EMPTY_LIST;
List<String> s = Collections.emptyList();
Map:
Map m = Collections.EMPTY_MAP;
Map<String> ms = Collections.emptyMap();
Set:
Set s = Collections.EMPTY_SET;
Set<String> ss = Collections.emptySet();
Notice:
Implementations of this method need not create a separate XXX object
for each call. Using this method is likely to have comparable cost to
using the like-named field. (Unlike this method, the field does not
provide type safety.)

How to subtract collections with Comparator interface instead of overriding equals

I want to compute differences between collections. When using CollectionUtils.subtract() for custom comparison I need to override the object's equals() method. But what if I need to compare collections of objects of the same type but different comparison criterion? What about the Comparator interface, it seems perfectly suited here? AFAIK Comparator is mainly used for sorting. Isn't there a method that uses Comparators for subtracting?
static <Type> Collection<Type> subtract(Collection<Type> a, Collection<Type> b, Comparator<Type> c) {
Set<Type> subtrahend = new TreeSet<Type>(c);
subtrahend.addAll(b);
Collection<Type> result = new ArrayList<Type>();
for (Type item: a) {
if (!subtrahend.contains(item)) result.add(item);
}
return result;
}
The subtrahent tree-set is not necessary, but will improve performance for large b.
If you have an ArrayList, multiple removes can be more expensive than taking a copy.
List<Type> list = /* ArrayList */
Set<Type> toRemove = /* HashSet */
List<Type> copy = new ArrayList<Type>(list.size());
for(Type t: list)
if(!toRemove.contains(t))
copy.add(t);
list = copy;
Personally I would use a loop. Its likely to be shorter and clearer.
Collection<Type> collection =
for(Iterator<Type> i=collection.iterator(); i.hasNext();)
if (i.next() is to be removed)
i.remove();
The reason an Iterator is used explicitly is to use the Iterator.remove() which avoids a ConcurrentModificationException. Another way to avoid it is to use a copy of the collection which might be preferred.
for(Type t : new ArrayList<Type>(collection))
if (t is to be removed)
collection.remove(t);
This doesn't perform as well but may perform well enough.

sorting arrayLists

I have a scenario where I have two ArrayLists
ArrayList<String> sortedArrayList
ArrayList<String> unSortedArrayList
I have to sort unSortedArrayList depending on the sortedArrayList.
i.e, sortedArrayList is already sorted, now based on sortedArrayList, I have to sort unSortedArrayList.
unSortedArrayList size is <= to the size of sortedArrayList.
Is there a Java API for that?
Any help is appreciated.
Using Google Guava's excellent Ordering class:
Collections.sort(unSortedArrayList, Ordering.explicit(sortedArrayList));
EDIT You can also do
List<whatever> sortedList = Ordering.explicit(sortedArrayList).immutableSortedCopy(unsortedArrayList);
As I understand what you have is that each element in list 1 has a corresponding element in list 2, and you want list 2 sorted into the order of the 'corresponding' elements. Your best approach is to create an object to contain both Strings:
class StringPair {
String s1;
String s2;
}
Now make an array list of StringPairs and sort it based on the value of s1.
List<String> newSortedList = new ArrayList<String>();
for(String currentSortedStr:sortedList){
if(unsortedList.size==0)break;
if(unsortedList.remove(currentSortedStr)){
newSortedList.add(currentSortedStr);
}
}
You can do something like this if you mean what #Sam Dufel says in the comment
As far as I know there is not such API method for this case.
This is not gonna take care of duplicates. remove will remove only the first occurence of that object. At the if the unsorted list size is greater than 0, you can say it contains duplicates. And if you need duplicates as well, you may wanna add some code to handle that case as well.
or if you mean the normal sorting;
Collections.sort(List<T>) will do the sorting for you.
Another way of doing it;
Collections.sort(unsortedList,new CustomComparator(sortedList));
public class CustomComparator implements Comparator<String>{
private List<String> sortedList;
public CustomComparator(List<String> sortedList){
this.sortedList = sortedList;
}
#Override
public int compare(String o1, String o2) {
return sortedList.indexOf(o1)-sortedList.indexOf(o2);
}
}
Although your question is not clear enough I think that the following will help you.
You can use Collections.sort() to sort list. If you need some custom modification to sort mechanism implement your own Comparator and use 2 args version of this method: Collections.sort(list, comparable)

Categories

Resources