Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to know which element matched in java-8 anymatch?

Assuming I have an enum

enum Country {
    China, 
    USA, 
    Others
}

Say I have a list1 = ["China", "Shanghai", "Beijing"] and a check for isChina, if true, then return Country.China.

list2 = ["USA", "Dallas", "Seattle"] and a method checks for isUSA, if true then return Country.USA.

If USA or China is missing from the list, then return Country.Others.

Assumption: A list will always contain only 1 country followed by cities in that country.

[Edit] Do not assume, country would be first element in the array.

While I find it extremely easy to implement in Java-7, I am not sure of the most elegant way to do this using streams

for (String str: list) {
   if (str.equals("China")) {
       return Country.China  
   } 
   if (str.equals("USA")) {
       return Country.USA; 
   }
}
return Country.Other;

I am looking for a clean implementation using Streams.

like image 261
JavaDeveloper Avatar asked Jan 07 '19 23:01

JavaDeveloper


Video Answer


4 Answers

Use a filter operation for the conditions and findFirst to get the first match, then transform to the respective Country.China or Country.USA otherwise return Country.Others if there was not match.

 return list.stream()
            .filter(str -> "China".equals(str) || "USA".equals(str))
            .findFirst()
            .map(s -> "China".equals(s) ? Country.China : Country.USA)
            .orElse(Country.Others);

Alternatively:

return Stream.of(Country.values()) // or Arrays.stream(Country.values())
             .filter(o -> list.contains(o.toString()))
             .findFirst().orElse(Country.Others);

The first solution will always check for "China" before checking for "USA" which is the exact equivalent of your imperative approach, However, the latter doesn't always respect that order, rather it depends on the order of the enum constants declarations in Country.

like image 53
Ousmane D. Avatar answered Sep 22 '22 14:09

Ousmane D.


If the string matches the enum token then it's pretty simple:

return Arrays.stream(Country.values())
    .filter(c -> c.name().equals(list.get(0))
    .findAny().orElse(Country.Others);

This is assuming the first element of the list is the name as you specified.

like image 31
sprinter Avatar answered Sep 23 '22 14:09

sprinter


A simpler solution using the ternary operators would be :

Country searchCountry(List<String> list) {
    return list.contains("China") ? Country.China : 
            list.contains("USA") ? Country.USA : Country.Others;
}
like image 21
Naman Avatar answered Sep 20 '22 14:09

Naman


Country findCountry(List<String> countries) {
  return Arrays.stream(Country.values())
    .filter(country -> countries.contains(country.name()))
    .findAny()
    .orElse(Country.Others);
}
like image 41
Adam Siemion Avatar answered Sep 23 '22 14:09

Adam Siemion