Pawan
Pawan

Reputation: 32321

Comparing Two ArrayLists to Get Unique and Duplicate Values

I have two ArrayLists as shown - pinklist and normallist. I am comparing both of them and finding the unique and duplicate values from both as shown below in code:

List<String> pinklist = t2.getList();
List<String> normallist = t.getList();
ArrayList<String> duplicatevalues = new ArrayList<String>();
ArrayList<String> uniquevalues = new ArrayList<String>();

for (String finalval : pinklist) {
    if (pinklist.contains(normallist)) {
        duplicatevalues.add(finalval);
    } else if (!normallist.contains(pinklist)) {
        uniquevalues.add(finalval);
    }
}

I am getting the duplicateValues properly, but I am not getting the unique values.

Upvotes: 4

Views: 67638

Answers (7)

Vitrag Doshi
Vitrag Doshi

Reputation: 1

Here's my solution to the problem. We can create a set containing elements from both the lists.

For the unique elements, using the Stream API, we can filter out the elements based on the predicates returning XOR of contains method. it will return true only for true ^ false OR false ^ true, ensuring only one of them contains it.

For the distinct elements, simply change the XOR to &&, and it'll check if both lists have the objects or not.

Code:

private static void uniqueAndDuplicateElements(List<String> a, List<String> b) {
    Set<String> containsAll = new HashSet<String>();
    containsAll.addAll(a);
    containsAll.addAll(b);

    List<String> uniquevalues = containsAll.stream()
                                .filter(str -> a.contains(str) ^ b.contains(str))
                                .collect(Collectors.toList());
        
    List<String> duplicatevalues = containsAll.stream()
                                   .filter(str -> a.contains(str) && b.contains(str))
                                   .collect(Collectors.toList());

    System.out.println("Unique elements from both lists: " + uniquevalues);
    System.out.println("Elements present in both lists: " + duplicatevalues);
}

Upvotes: 0

Mordechai
Mordechai

Reputation: 16214

this should do:

List<String> pinklist = t2.getList();
List<String> normallist = t.getList();

ArrayList<String> duplicates = new ArrayList<String>(normallist);
duplicates.retainAll(pinklist);

ArrayList<String> uniques = new ArrayList<String>(normallist);
uniques.removeAll(pinklist);  

Explaination:

  • Every List can take another list as a constructor parameter, and copy it's values.

  • retainAll(list2) will remove all entries, that does not exist in list2.

  • removeAll(list2) will remove all entries, that does exist in list2.

  • We don't want to remove/retain on the original lists, because this will modify it, so we copy them, in the constructor.

Upvotes: 20

Taavi Kivimaa
Taavi Kivimaa

Reputation: 252

Try ListUtils https://commons.apache.org/proper/commons-collections/apidocs/org/apache/commons/collections4/ListUtils.html

To get duplicate values use ListUtils.intersection(list1, list2) To get unique values you could use ListUtils.sum(list1, list2) and then subtract the duplicates list

Upvotes: 2

Rahul Ghadage
Rahul Ghadage

Reputation: 153

Using Java8 Stream API we can filter lists and get expected results.

List<String> listOne = // Your list1
List<String> listTwo = // Your list2

List<String> uniqueElementsFromBothList = new ArrayList<>();
List<String> commonElementsFromBothList = new ArrayList<>();

// Duplicate/Common elements from both lists
commonElementsFromBothList.addAll(
         listOne.stream()
        .filter(str -> listTwo.contains(str))
        .collect(Collectors.toList()));

// Unique element from listOne
uniqueElementsFromBothList.addAll(
         listOne.stream()
        .filter(str -> !listTwo.contains(str))
        .collect(Collectors.toList())); 

// Unique element from listOne and listTwo 
// Here adding unique elements of listTwo in existing unique elements list (i.e. unique from listOne)
uniqueElementsFromBothList.addAll(
         listTwo.stream()
        .filter(str -> !listOne.contains(str))
        .collect(Collectors.toList()));

Upvotes: 0

Jon Skeet
Jon Skeet

Reputation: 1500055

You're ignoring finalval in your conditions, instead asking whether one list contains the other list.

You could do it like this:

// Variable names edited for readability
for (String item : pinkList) {
    if (normalList.contains(item)) {
        duplicateList.add(item);
    } else {
        uniqueList.add(item);
    }
}

I wouldn't really call these "unique" or "duplicate" items though - those are usually about items within one collection. This is just testing whether each item from one list is in another. It's more like "existing" and "new" in this case, I'd say.

Note that as you're treating these in a set-based way, I'd suggest using a set implementation such as HashSet<E> instead of lists. The Sets class in Guava provides useful methods for working with sets.

Upvotes: 17

MD Sayem Ahmed
MD Sayem Ahmed

Reputation: 29166

Do it this way -

for (String finalval : pinklist)
{   
    if(normallist.contains(finalval))
    {
        // finalval is both in pinklist and in
        // normallist. Add it as a duplicate.
        duplicatevalues.add(finalval);  // this will get you the duplicate values
    }
    else {
        // finalval is in pinklist but not in
        // normallist. Add it as unique.
        uniquevalues.add(finalval);    // this will get you the values which are in 
                                       // pinklist but not in normallist
    }
}

// This will give you the values which are
// in normallist but not in pinklist.
for(String value : normallist) {
    if(!pinklist.contains(value)) {
        uniquevalues.add(value);
    }
}

Upvotes: 0

Sumit Desai
Sumit Desai

Reputation: 1760

Why are you passing entire list to the contains method? You should pass finalval rather.

Upvotes: -1

Related Questions