How to get unique values in List - java

I have 2 text files with data. I am reading these files with BufferReader and putting the data of one column per file in a List<String>.
I have duplicated data in each one, but I need to have unique data in the first List to confront with the duplicated data in the second List.
How can I get unique values from a List?

It can be done one one line by using an intermediate Set:
List<String> list = new ArrayList<>(new HashSet<>(list));
In java 8, use distinct() on a stream:
List<String> list = list.stream().distinct().collect(Collectors.toList());
Alternatively, don't use a List at all; just use a Set (like HashSet) from the start for the collection you only want to hold unique values.

Convert the ArrayList to a HashSet.
List<String> listWithDuplicates; // Your list containing duplicates
Set<String> setWithUniqueValues = new HashSet<>(listWithDuplicates);
If for some reason, you want to convert the set back to a list afterwards, you can, but most likely there will be no need.
List<String> listWithUniqueValues = new ArrayList<>(setWithUniqueValues);

In Java 8:
// List with duplicates
List<String> listAll = Arrays.asList("A", "A", "B", "C", "D", "D");
// filter the distinct
List<String> distinctList = listAll.stream()
.distinct()
.collect(Collectors.toList());
System.out.println(distinctList);// prints out: [A, B, C, D]
this will also work with objects, but you will probably have to adapt your equals method.

i just realize a solution may be it can be helpful for other persons.
first will be populated with duplicated values from BufferReader.
ArrayList<String> first = new ArrayList<String>();
To extract Unique values i just create a new ArrayList like down:
ArrayList<String> otherList = new ArrayList<>();
for(String s : first) {
if(!otherList.contains(s))
otherList.add(s);
}
A lot of post in internet are all speaking to assign my Arraylist to a List , Set , HashTable or TreeSet.
Can anyone explain the difference in theory and whitch one is the best tu use in practice ?
thnks for your time guys.

Related

Convert Set to List for csv elements Java 8

I create the below Set:
Set<String> set = new HashSet<>();
set.add("Test1,Test2");
set.add("Test3,Test4");
I need to convert this Set to a List by splitting of all elements separately.
Final List should contain four elements, i.e.
Test1, Test2, Test3, Test4
Please clarify how to convert the Set to a List using Java 8.
I tried like this, but it returns a List of List of String, instead of a List of String.
set.stream().map(x-> Arrays.asList(x.split(","))).collect(Collectors.toList());
You need to use flatMap(...) to convert the list of list of elements into a list of elements. Into flatMap(...) you need to provide a lamba or method reference to convert the elements of the stream (the lists) into a stream of elements (the actual elements of the lists).
Since here your elements in the stream are lists, you can do Collection::stream but if you were to keep the array (not using Arrays.asList(...)) you could also do Arrays::stream.
A final possible solution could be:
set.stream().map(x -> x.split(",")).flatMap(Arrays::stream).collect(Collectors.toList())
Or this less efficient solution:
set.stream().map(x -> Arrays.asList(x.split(","))).flatMap(Collection::stream).collect(Collectors.toList())
set.stream()
.map(i -> Arrays.asList(i.split(",")))
.flatMap(list -> list.stream())
.sorted()
.collect(Collectors.toList());
I am guessing set is a Set of Strings, since you can split the items in the lambda. String.split returns an array of Strings, you convert it to the List with Arrays.asList. So now you have Stream of List<String>s, meaning, by collecting them with toList, it gives you List<List<String>>. So before collecting the items, you need to call flatMap(list -> list.stream()) so it becomes Stream of Strings
Why not consider a simpler approach?
HashSet<String> mySet = new HashSet<>();
List<String> myList = new ArrayList<>();
for (String string : mySet) {
String[] strings = string.split(",");
myList.addAll(Arrays.asList(strings));
}
This is still using Java 8.

Comparing string ArrayList

I have 2 array list that contain strings:
List1 = [no, yes, ok, not]
List2 = [no, but, vote, check]
Now, how do I compare List1 with List2 and remove the words in List1 if the same word are found in List2. The sorted word(without the same word) are stored in another arraylist.
Outcome should be like this:
List3 = [yes, ok, not]
If you want to store the result in a new list, you need to clone List1 first:
ArrayList list3 = (ArrayList) list1.clone();
or
ArrayList list3 = new ArrayList(list1);
Then use removeAll:
list3.removeAll(list2);
ArrayList provides method to remove all object present in another list.
Refer Removing elements present in collection
In your case list1.removeAll(list2) should solve your problem
You can create third list , add to it your two lists and find in it third list same words. When you find them , delete one.So you'll check your third list with equals().
I suppose you didn't know about the removeAll(Collection c) method present for ArrayLists or just want another way of doing it.
Since you mention that you need to remove the duplicated words from list1, initialize a HashSet and add all the values in list2 to the Set, like so,
Set<String> set = new HashSet<String>();
for(String s: list2)
set.add(s);
Now, do the same with a clone of list1, taking care to remove the strings from list1.
String[] list3 = new String[list1.size()];
list1.toArray(list3);
for(String s: list3)
if(!set.add(s))
list1.remove(s);
This is done in O(n) time, but takes some auxiliary storage. Please let me know if this solved your problem.

Merge two list into a single list

I have a ArrayList as below.
ArrayList<ArrayList<String>> a = new ArrayList<ArrayList<String>>();
Where ArrayList 'a' contains two ArrayList of string as below.
[a,b,c,d] & [1,2,3,4]
How to merge these two list into a single list as below.
[a,b,c,d,1,2,3,4]
Thanks In Advance.
You combine a foreach loop and the addAll method.
Example
ArrayList<String> combined = new ArrayList<String>();
for(ArrayList<String> list : a) {
combined.addAll(list);
}
How this works?
A for each loop will traverse through every member of a Collection. It has a temporary variable, in this case list that it assigns the current element too. All you're doing is adding every element inside each value for list, to one ArrayList named combined.
Just iterate through all the inner lists of a using foreach loop and addAll to result arraylist
ArrayList<String> merged = new ArrayList<String>();
for(ArrayList<String> list : a){
merged.addAll(list);
}
EDIT:
As #Lubo pointed out.
Note that this way you can end up with many arrays being created and thrown away internally in ArrayList. If you have large lists (number of contained elements), consider looking here: Union List
This should work
ArrayList<ArrayList<String>> a = new ArrayList<ArrayList<String>>();
List<String> result = new ArrayList<String>();
for (ArrayList<String> arrayList : a) {
result.addAll(arrayList);
}
Look into main loop and get each list in it and add to your result list.
We have some other ways too, If you can use Apache commons-collection
ListUtils.union(java.util.List list1, java.util.List list2)
Returns a new list containing the second list appended to the first list.
Use ArrayList.addAll(). Something like this should work (assuming lists contain String objects; you should change accordingly).
List<String> combined = new ArrayList<String>();
combined.addAll(firstArrayList);
If you need an Iterable, you can use Guava:
Iterables.concat(Iterable<? extends Iterable<? extends T>> inputs)
And if you really need a List, you can cast a resulting Iterable to a List using this:
Lists.newArrayList(Iterable<? extends E> elements)
or
Lists.newLinkedList(Iterable<? extends E> elements)
Java 8 streams provide another solution:
List<List<String>> list = Arrays.asList(
Arrays.asList("1", "2"),
Arrays.asList("3", "4"),
Arrays.asList("5", "6")
);
List<String> merged = list
.stream()
.reduce(new ArrayList<>(),(accumulator, sublist) -> {accumulator.addAll(sublist);return accumulator;});
System.out.println(merged);
It is similar to the accepted answer: you loop through your list (using Stream.reduce) to add all of your sublists elements to your merged list.
List<Integer> one = Arrays.asList(1, 2,3);
List<Integer> two = Arrays.asList(4, 5,6);
List<Integer> out = Stream.of(one, two)
.collect(ArrayList::new, (listStream, item) -> listStream.addAll(item), (item1, item2) -> {});
System.out.println(out);
Merging lists without loop with Guava
Using FluentIterable.transformAndConcat.
Applies function to each element of this fluent iterable and returns a fluent iterable with the concatenated combination of results. function returns an Iterable of results.
Usage
List<String> combined = FluentIterable.from(a)
.transformAndConcat(Functions.identity())
.toList();

remove duplicated elements from an array list [duplicate]

This question already has answers here:
Remove duplicates from ArrayLists
(14 answers)
Closed 9 years ago.
In my program I have an array list containing product objects in it. I want to remove duplicated product objects from it. Is there any efficient way other than looping over each element and compare them.
just add all element into set. it wont allow duplicate values
List<Product> list=new ArrayList<>();
Set<Product> set=new HashSet<>();
set.addAll(list);
Just pass your list Collection to Hashset constructor and Get it back.
Then that one liner will be,
list = new ArrayList<E>(new HashSet<E>(list));
You can just put element into Set. Set keep unique values only.
List<String> list=new ArrayList<>();
Set<String> set=new HashSet<>();
set.addAll(list); // now you have unique value set
If you want to final result as unique value List just you need to get this Set as List
List<String> uniqueValList=new ArrayList<>(set);
You can use a Set but you will loose the original order of your list.
What you can do to keep the order is:
Set<E> copied = new HashSet<>();
List<E> res = new ArrayList<>();
for(E e : originalList) {
if(!copied.contains(e)) {
res.add(e);
}
copied.add(e);
}
Use Set instead of list it will remove duplicates
Try to use Set instead of List. Set wont allow duplicate values.
The advice above to use Set is good - but if you need to keep the order just use a LinkedHashSet http://docs.oracle.com/javase/7/docs/api/java/util/LinkedHashSet.html
List<String> list = ...
Set<String> set = new LinkedHashSet<>(list);
list.clear();
list.addAll(set);
That will preserve order and remove all duplicates.
The result will be case sensitive though in the case of strings.

INTERSECT result of 2 ArrayList containing Integer values

I've two ArrayList both containing Integer values. My objective is to get identical/common/duplicate values comparing these 2 list. In other words (in SQL parlance), I need the INTERSECT result of two lists, that is, values that appear in both list.
Example:
ArrayList<Integer> list1 = new ArrayList<Integer>();
list1.add(100);
list1.add(200);
list1.add(300);
list1.add(400);
list1.add(500);
ArrayList<Integer> list2 = new ArrayList<Integer>();
list2.add(300);
list2.add(600);
One kind of implementation/solution I could think along is looping one of the list something like:
ArrayList<Integer> intersectList = new ArrayList<Integer>();
for (Integer intValue : list1)
{
if(list2.contains(intValue))
intersectList.add(intValue);
}
In this case, intersectList would contain only 1 Integer item being added, that is 300, which appears in both list.
My question is, are there any better/fastest/efficient way of implementing this logic? Any options available in Apache Commons library?. Any other ideas/suggestions/comments are appreciated.
NOTE: For illustration purpose, I've just shown here 5 items and 2 items being added into the list. In my real-time implementation, there will be more than 1000 elements in each list. Therefore, performance is also a key factor to be considered.
If you're okay with overwriting result for list1:
list1.retainAll(list2);
otherwise clone/copy list1 first.
Not sure on performance though.
list1.retainAll(list2)//for intersection
Use ListUtils from org.apache.commons.collections if you do not want to modify existing list.
ListUtils.intersection(list1, list2)

Categories