user11535503
user11535503

Reputation:

Java checking how many elements are the same in two Lists

Let's suppose I have a List

List<String> allElements = new ArrayList<>(Lists.asList("A", "B", "C", "D", "F")); 

And then another List

List<String> randomElements = new ArrayList<>(Lists.asList("B", "D", A", "Z"));

Now I want to check if allElements contains 3 or more elements from randomElements. If only 2 or less then I don't want it to fire up true. (The example above should return true) How would I go about this? I could use allElements.deleteAll(randomElements) and get the length of allElements, but that's not ideal since I want to work with the variable's values later (and this way I would delete them) and using deleteAll each loop on temp variables isn't very elegant. Is there a different way? In a short way, I want to get the amount of elements that have the same value with different List no matter what index they're at.

edit: I used a solution from @Jesper Hustad

boolean listCheck(ArrayList allElements, ArrayList randomElements){
    int count = 0;
        for(Element a: allElements){
            for(Element b : randomElements){
                if(a==b){
                    count++;
                }
            }
        }
    return count==3;
}

I don't know if this is the most efficient solution (probably not), but it's the most clean for me.

Upvotes: 2

Views: 1842

Answers (4)

Boris Azanov
Boris Azanov

Reputation: 4501

Best way to do this is use HashSet data structure from java.util package:

import java.util.*;

List<String> allElements = new ArrayList<>(Arrays.asList("A", "B", "C", "D", "F"));
List<String> randomElements = new ArrayList<>(Arrays.asList("B", "D", "A", "Z"));

Set<String> allElementsSet = new HashSet<>(allElements);
int count = 0;
Iterator<String> randomElementsIt = randomElements.iterator();
List<String> resultList = new ArrayList<>();
while (randomElementsIt.hasNext()) {
    String nextRandom = randomElementsIt.next();
    if (allElementsSet.contains(nextRandom)) {
        count++;
    }
    if (count == 3) {
        resultList.add(nextRandom);
        count = 0;
    }
}
// resultList - contains all elements

or you can use more functional way:

List<String> result = randomElements.stream()
   .filter(allElementsSet::contains)
   .map(randomElement -> new Pair<>(randomElement, 1))
   .collect(Collectors.toMap(
       pair -> pair.fst,
       pair -> pair.snd,
       Integer::sum)
   )
   .entrySet().stream()
   .filter(pair -> pair.getValue() >= 3)
   .map(Map.Entry::getKey).collect(Collectors.toList());

HashSet structure is useful for fast finding element is in some group. Method contains works for O(1). In this decision lists are not changes and you just create a new data structure from randomElements list.

Upvotes: 0

Jesper Hustad
Jesper Hustad

Reputation: 352

This should work, but im not sure it's the most efficient:

boolean listCheck(ArrayList allElements, ArrayList randomElements){
    int count = 0;
        for(Element a: allElements){
            for(Element b : randomElements){
                if(a==b){
                    count++;
                }
            }
        }
    return count==3;
}

Upvotes: 0

Ryuzaki L
Ryuzaki L

Reputation: 40098

You can use the stream but i would suggest to use limit for better performance. As suggested in comment by @Andy Turner you can use Set for better improvement

return randomElements.stream()
                     .filter(i->list1.contains(i))
                     .limit(3)
                     .count() >= 3

Upvotes: 4

zeg
zeg

Reputation: 586

This sounds like a mathematical problem.

Basically you need to compare each element from list allElements with list randomElements. You can do that by implementing two for-loops like this

int countEqualMatches = 0;
for(String a : allElements){
    for(String b : randomElements){
        if(a.equals(b)){
            countEqualMatches++;
        }
    }
}
System.out.println(countEqualMatches);

Also if allElements contains "A" two times and randomELements contains "A" two times you would get a count of 4 matches. Depends on the situation if you want this.

Also the first approach needs a lot of comparison tasks and is kinda cpu heavy if your lists get longer

If you can do something like an "alphbetical-ordering" of one or both lists you can implement a far more efficient method to compare the two lists. Normally you can just use java list.order(); function

if both lists are ordered you can start on the very lowest elements and compare these. if they are equal do ++, if not shift the smaller element away on one list and compare again. this way you get a 2N instead of a N^2 runtime in your compare function, however it might cost some to order the lists beforehand...

Pick whatever fits you better :)

Upvotes: 0

Related Questions