Home > Back-end >  How to filter a list of String down to a distinct list made of string suffices in Java 8 Streams
How to filter a list of String down to a distinct list made of string suffices in Java 8 Streams

Time:09-26

I am new to Java streams but need to master by practice really!

The collection input is made up of strings e.g. [name][dot][country], example as follows:

 - JAMES.BRITAIN
 - JOHN.BRITAIN
 - LEE.BRITAIN
 - GEORGE.FRANCE
 - LEON.FRANCE
 - MARSELLE.FRANCE
 - KOFI.GHANA
 - CHARLIE.GHANA

Please, how do I return a list of unique countries in a single stream statement?

Expected result will be a distinct list as follows:

 - BRITAIN
 - FRANCE
 - GHANA

In the real code the streams statement below gives me the list to be filtered i.e.:

List<String> allSolrCollections =  (List<String>) findAllCollections()
                    .getJsonArray(SOLR_CLOUD_COLLECTION)
                    .getList()
                    .stream() 
                    .map(object -> Objects.toString(object, null))
                    .collect(Collectors.toList());

CodePudding user response:

  • for the first part of problem, you need to convert each entry to corresponding country. so, you could use String.split function and keep the country part.
  • for the second part you could take advantage of the Stream.distinct function that will remove duplicates from incoming stream.

finally, this should work:

List<String> res = list.stream()
        .map(s -> s.split("\\.")[1])
        .distinct()
        .collect(Collectors.toList());

CodePudding user response:

If you want to be careful about format it would be worth using a regular expression. This also makes the meaning of the code clearer to a reader.

Pattern inputPattern = Pattern.compile("- (?<name>[A-Z] )\\.(?<country>[A-Z] )");
list.stream()
    .map(inputPattern::match)
    .filter(Matcher::matches)
    .map(m -> m.group("country"))
    .distinct()
    .toList();

This ignores lines that don't match the expected format.

CodePudding user response:

Alternative solution

You can use the advantage of the method Pattern#splitAsStream(CharSerquence). Once you split each line into a new Stream, skip the first item, flatMap the result into a new Stream and produce a Set.

final Pattern pattern = Pattern.compile("\\.");

final Set<String> result = list.stream()
        .flatMap(string -> pattern.splitAsStream(string).skip(1))
        .collect(Collectors.toSet());
[GHANA, FRANCE, BRITAIN]
  • Related