4

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.

7 Answers 7

20

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.

Sign up to request clarification or add additional context in comments.

5 Comments

Care to explain your code? Especially the part where you're cloning the list.
@Makoto Was just in a rush, of coming up with an answer. I immediately started the editing.
retainAll and removeAll will return boolean value so you cannot declare ArrayList
The thing I don't get is why asker has accepted manual implementation over this out-of-box method.
@mordechai small correction in the code above dublicates to duplicates. - thank you very helpful post.
17

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.

Comments

2

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

Comments

0

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);
    }
}

2 Comments

Care to explain your code? Code-only answers aren't all that great.
@Makoto: I have explained my code now. I think it's understandable right now.
0

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()));

Comments

0

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);
}

Comments

-1

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.