Home > Software design >  Find the Count of common elements within the two nested Lists
Find the Count of common elements within the two nested Lists

Time:08-02

Compare each element present in list of String lists object1 with another object object2 in Java

I have a list of String lists initialized to object1 as mentioned below:

List<List<String>> object1 = Arrays.asList(Arrays.asList("A", "B", "C"),
                                       Arrays.asList("D", "E", "F"), 
                                       Arrays.asList("G", "H", "I"));

I have a another list of String lists initialized to object2 as mentioned below:

List<List<String>> object2 = Arrays.asList(Arrays.asList("A", "B", "C"),
                                       Arrays.asList("D", "E", "F"), 
                                       Arrays.asList("G", "H", "J"));

How do I compare each element between two objects one by one in same order

Need to initialize a counter variable to track number of common elements present between two objects.

Expected result : 8

CodePudding user response:

You can generate a Map representing the number of occurrences of each element in a list for both lists.

And then add up the values associated with keys that are present in both maps of frequencies by choosing the smallest value in every pair of values.

If you're comfortable with streams, this logic can be implementing like that:

public static Map<String, Long> getFrequencies(List<List<String>> list) {
    
    return list.stream()
        .flatMap(List::stream)
        .collect(Collectors.groupingBy(
            Function.identity(),
            Collectors.counting()
        ));
}

public static long countCommonValues(Map<String, Long> map1, Map<String, Long> map2) {
    
    return map1.entrySet().stream()
        .filter(entry -> map2.containsKey(entry.getKey()))
        .mapToLong(entry -> Math.min(entry.getValue(), map2.get(entry.getKey())))
        .sum();
}

main()

public static void main(String[] args) {
    List<List<String>> list1 = List.of(
        List.of("A", "B", "A"),
        List.of("D", "E", "H"),
        List.of("G", "H", "I"));
    
    List<List<String>> list2 = List.of(
        List.of("A", "B", "C", "D"),
        List.of("D", "E", "F", "A"),
        List.of("G", "H", "J", "H"));

    System.out.println(countCommonValues(getFrequencies(list1), getFrequencies(list2)));
}

Output:

8   // "A", "A", "B", "D", "E", "G", "H", "H"

A link to Online Demo


In case if order is important and nested lists are not guaranteed to be of the same size, we can flatten both lists and then compare elements at corresponding indices.

public static <T> long countCommonValues(List<List<T>> list1, List<List<T>> list2) {
    
    List<T> flattened1 = flatten(list1);
    List<T> flattened2 = flatten(list2);
    
    return IntStream.range(0, Math.min(flattened1.size(), flattened2.size()))
        .filter(i -> flattened1.get(i).equals(flattened2.get(i)))
        .count();
}

public static <T> List<T> flatten(List<List<T>> list) {
    return list.stream()
        .flatMap(List::stream)
        .toList();
}

CodePudding user response:

To get your required output the simplest way is to use 2 nested loops to iterate over both Lists and Sublists and check each element for equality, using a simple counter variable to keep track of equal elements:

int equalElements = 0;
for (int i = 0; i < object1.size() && i < object2.size(); i  ) {
    final List<String> subList1 = object1.get(i);
    final List<String> subList2 = object2.get(i);
    for(int x = 0; x < subList1.size() && x < subList2.size(); x  ) {
        if (Objects.equals(subList1.get(x), subList2.get(x))) {
            equalElements  ;
        }
    }
}
    
System.out.println(equalElements);
  • Related