0

I have this brainer. I need to iterate over a Map<UUID, List<Items>> groups and return a single value!

Can I do this with Lambda and how? (how do I get the id of the group that has an item of TYPE_12? The item of TYPE_12 is going to be only one across all groups)

Thanks in advance this is my for code:

String theId = null; for(Map.Entry<UUID, List<Item>> group : groupsOfItems) { for (Item item : group.getValue()) { if (item.getType() == Types.TYPE_12) { theId = group.getKey().toString(); break; } } } 
0

3 Answers 3

2

If you want to use functional style, you can create a stream from you map entry set, then expand it to get a stream of each item in underlying lists :

Optional<String> result = groupOfItems.entrySet().stream() .flatMap(entry -> entry.getValue().stream()) .filter(item -> Types.TYPE_12.equals(item.getType)) .map(Item::getId) .findAny(); result.ifPresent(id -> System.out.println("A match has been extracted: "+id)); 

As is, the functional style way is not more performant than the imperative one, but is more easily adaptable. Let's say you want to know if there's more than one match, you can replace findAny by a collector with a limit :

List<String> matchedIds = groupOfItems.entrySet().stream() .flatMap(entry -> entry.getValue().stream()) .filter(item -> Types.TYPE_12.equals(item.getType)) .map(Item::getId) .limit(2) .collect(Collectors.toList()); if (matched.isEmpty()) System.out.println("No match found"); else if (matched.size() == 1) System.out.println("Exactly one match found: "+matched.get(0)); else System.out.println("At least two matches exist"); 

Stream usage also allow parallelization if necessary, by simply adding parallel() step to your pipeline.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks! Great! I'll try this out soon! It looks like what I need. I am trying to orient myself towards functional style.
1

Here is a solution using lambdas. The difference is this one does not use flatMap and throws an exception if the required value is not found (based on the question stating that there should be one and only one TYPE_12 in the whole value set of the map).

UUID result = groupsOfItems.entrySet().stream() .filter(e -> e.getValue().stream() .anyMatch(item -> item.getType() == TYPE.TYPE_12)) .findAny().orElseThrow().getKey(); 

Comments

0
String theId = null; find: for (Map.Entry<UUID, List<Item>> group : groupsOfItems.entrySet()) { for (Item item : group.getValue()) { if (item.getType() == Types.TYPE_12) { theId = group.getKey().toString(); break find; } } } 

No don't use lambda for this. Just use java labels to break out of both for loops after you found your entry. (Notice the find: before the first for loop. That's a label and once you call break find; it will break out of the block marked with that label)

Also you need to use .entrySet in the first for loop. Just passing groupsOfItems won't be enough

3 Comments

Does it work for you @gai-jin??
nope, I have it with labels and all in my code (in here I quickly took a sample, more like a suedo code). I want to do it with LAMBDAs, if it is possible. Which is one of my questions. Just for the sake of re-making it with lambds.
Ok never mind then

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.