2

Here I am posting sample datastructure

I have a list List<Result> resultsList;

class Result { 
    String name; 
    Map<String,Integer> resultMap; 
}

Now I would like to stream through this list and get the map.

resultList.stream().filter(result->"xxx".equals(result.getName()))
                   .map(result->result.getResultMap);

It returns Stream<Map<String,Integer>> but I need only Map<String,Integer>.

How to get it using java 8 streams?

Update:

As geneqew mentioned

This is how my datastructure looks

List<Result> resultsList;

Map<String, Integer> map1 = new HashMap<>();
map1.put("m1", 1);
Map<String, Integer> map2 = new HashMap<>();
map2.put("m2", 2);
Map<String, Integer> map3 = new HashMap<>();
map3.put("m3", 3);

results = Arrays.asList(
        new Result("r1", map1),
        new Result("r2", map2),
        new Result("r3", map3)
);

I would like to retrieve single map based on name.

for (Result result: resultsList)
{
   if ('xxx'.equals(result.getName())
   {
      return result.getResultMap();
   }
} 
2
  • 1
    Maybe the easiest would be if you posted non-stream code that does what you want. Commented Dec 13, 2018 at 7:36
  • 1
    Provide a concrete example and show what you'd expect the output to be. Normally streams are a pipeline to process each element, until you get to the final step. Commented Dec 13, 2018 at 7:38

4 Answers 4

4

Since you want to return the result map of the first Result element to pass your filter, you can obtain it with findFirst():

Optional<Map<String,Integer>> resultMap = 
    resultList.stream()
              .filter(result->"xxx".equals(result.getName()))
              .map(Result::getResultMap)
              .findFirst();

You can extract the Map from the Optional this way:

Map<String,Integer> resultMap = 
    resultList.stream()
              .filter(result->"xxx".equals(result.getName()))
              .map(Result::getResultMap)
              .findFirst()
              .orElse(null);
Sign up to request clarification or add additional context in comments.

5 Comments

In which case, why is OP using a list instead of a map to begin with?
Just to clarify, that's in no way a criticism of the answer.
@MadPhysicist Do you mean a Map<String,Result> instead of List<Result>? We don't know where the data is coming from.
Yes. If more than a couple of searches need to be done, it's likely to be worth the effort to construct a map.
Thank you. findAny() or findFirst() is answer for my question.
2

if you're only looking for one item:

resultList.stream()
          .filter(result -> "xxx".equals(result.getName()))
          .map(Result::getResultMap)
          .findAny();

if the filter could match more than one item then you'll need to flatten then toMap it:

resultList.stream()
          .filter(result-> "xxx".equals(result.getName()))
          .flatMap(result -> result.getResultMap().entrySet().stream())
          .collect(toMap(Map.Entry::getKey, Map.Entry::getValue));

if there can be duplicates then use the merge function to resolve collisions:

resultList.stream()
          .filter(result -> "xxx".equals(result.getName()))
          .flatMap(result -> result.getResultMap().entrySet().stream())
          .collect(toMap(Map.Entry::getKey, Map.Entry::getValue, (l, r) -> l));

4 Comments

The last one should work for all the cases, yet the reason you've listed all three solutions is the question is not clear.
@nullpointer true in the sense that it will work for all cases but why potentially process another "ton" of elements when you can short circuit with findAny. so if the OP is only after one item then this was the motivation behind using findAny, otherwise, they are probably looking for the toMap approach.
findAny wouldn't really work for the merge case, would it? and I would repeat, that really brings in the sense of question not being clear. isn't that quite visible in your own answer?
Thank you. findAny() or findFirst() is answer for my question.
1

Since you only wanted the map that matches the results' name then:

 results.stream()
               .filter(r-> r.getName().equals("r2"))
               .map(r-> r.getResultMap())
               .findFirst()
               .orElse(null); 

given you have a sample content of:

List<Result> results;

Map<String, Integer> map1 = new HashMap<>();
map1.put("m1", 1);
Map<String, Integer> map2 = new HashMap<>();
map2.put("m2", 2);
Map<String, Integer> map3 = new HashMap<>();
map3.put("m3", 3);

results = Arrays.asList(
        new Result("r1", map1),
        new Result("r2", map2),
        new Result("r3", map3)
);

A bit of explanation, you got a stream because the last operation in your stream is a map; assuming in your list its possible to have more than 1 result with the same name, findFirst will return the first match if found otherwise an empty optional is returned; Finally orElse to get terminate the stream, providing a null value on empty match.

1 Comment

Thank you. findAny() or findFirst() is answer for my question.
0

So I want to explain why you receive stream and not a map. The reason of this is because in the beginning you have List with Result objects that you filter by some criteria (in your case "xxx".equals(result.getName())).

Now you can have as result zero, one or more elements that will pass this criteria! Java does not know how many elements will pass at compile time and that is why you get Stream.

Imagine situation that you have two Result objects that have the same name 'xxx' then you will have two maps. The question is what you want to do? If you get only one of the maps you will loose information. If you want to get all of them, please try something like this:

        List<Map<String,Integer>> listWithResultMaps = resultList.stream()
                                                   .filter(result->"xxx".equals(result.getName()))
                                                   .map(result->result.getResultMap())
                                                   .collect(Collectors.toList());

Now in this listWithResultMaps you can process all maps that you have as result of your filter.

Good Luck!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.