Nibedita Behera
Nibedita Behera

Reputation: 3

How to get matching and non matching string from list


public class MyTest {

    public static void main(String args[]) {
        List<String> list1 = new ArrayList<String>();
        list1.add("Soumya Ranjan Das");
        list1.add("Test");

        List<String> list2 = new ArrayList<String>();
        list2.add("Soumya Das Ranjan");
        list2.add("Something");

        list1.retainAll("matching ----" + list2);
        System.out.println(list1);
    }
}
  1. see the above code where I am trying to retrieve matching data, does not matter if my string contains some random value.
  2. I'm expecting matching output should be "Soumya Das Ranjan" and non-matching should be "Something" and "Test"

Upvotes: 0

Views: 663

Answers (2)

0xh3xa
0xh3xa

Reputation: 4857

You can convert the list to Map<String, Set<String>> after converting every string to char[] then sort this char array

    public static void main(String[] args) {
        List<String> list1 = new ArrayList<>();
        list1.add("Soumya Ranjan Das");
        list1.add("Test");

        List<String> list2 = new ArrayList<>();
        list2.add("Soumya Das Ranjan");
        list2.add("Something");

        Collector<String, ?, Map<String, Set<String>>> groupingBy = Collectors.groupingBy(String::toString,
                Collectors.mapping(obj -> {
                    char[] arr = obj.toString().toCharArray();
                    Arrays.sort(arr);
                    return new String(arr);
                }, Collectors.toSet()));

        Map<String, Set<String>> collect = list1.stream().collect(groupingBy);
        Map<String, Set<String>> collect2 = list2.stream().collect(groupingBy);

        // Check if any elements from collect exists in collect2
        collect.entrySet().stream().filter(entry -> collect2.values().contains(entry.getValue())).forEach(entry -> {
            System.out.println(entry.getKey());
        }); // prints Soumya Ranjan Das

        // Check if any elements from collect not exists in collect2
        collect.entrySet().stream().filter(entry -> !collect2.values().contains(entry.getValue())).forEach(entry -> {
            System.out.println(entry.getKey());
        }); // prints Test
    }

Upvotes: 0

Nowhere Man
Nowhere Man

Reputation: 19565

You should process the strings in your lists in order to be able to compare any sequence of the words they contain.

You can achieve that by converting a String into set of strings for each list, finding an intersection and/or a difference between those lists and then rebuilding strings from sets:

private static List<Set<String>> convert(List<String> list) {
    return list.stream()
               .map(s -> Arrays.stream(s.split(" "))   // split string
                        .collect(Collectors.toCollection(LinkedHashSet::new))) // build set
               .collect(Collectors.toList()); // get list of sets
}

private static List<String> deconvert(List<Set<String>> listSets) {
    return listSets.stream()
                   .map(set -> String.join(" ", set)) // join strings in the set
                   .collect(Collectors.toList()); // get list of strings
}

// test
List<String> list1 = new ArrayList<>();
list1.add("Soumya Ranjan Das");
list1.add("Test");

List<String> list2 = new ArrayList<>();
list2.add("Soumya Das Ranjan");
list2.add("Something");

List<Set<String>> listSets1 = convert(list1);
List<Set<String>> listSets2 = convert(list2);

// intersection
listSets1.retainAll(listSets2);
System.out.println("similar elements: " + deconvert(listSets1));

List<Set<String>> listSets3 = convert(list1);
List<Set<String>> listSets4 = convert(list2);

// union of two lists
listSets3.addAll(listSets4);
// union - intersection = difference
listSets3.removeAll(listSets1);
System.out.println("different elements: " + deconvert(listSets3));

output:

similar elements: [Soumya Ranjan Das]
different elements: [Test, Something]

Upvotes: 1

Related Questions