map of map get outer map based on inner map value - java

How do I write below code using Java8?
for (Entry<Integer, Map<String, Object>> entry : data.entrySet()) {
Map<String, Object> value = entry.getValue();
if (value.get(Constants.USER_TRAN_ID).equals(stsTxn.getSeedTrade().getTransactionId())) {
closedTaxLotByTxnId = value;
break;
}
}
I am clueless after this
data.values().stream().map(e -> e.get(Constants.USER_TRAN_ID)).filter(txnId -> txnId.equals(stsTxn.getSeedTrade().getTransactionId()));

You don't need map. Just use filter with your criteria, and findFirst as terminal operation:
Optional<Map<String, Object>>
value = data.values()
.stream()
.filter(m -> m.get(Constants.USER_TRAN_ID).equals(stsTxn.getSeedTrade().getTransactionId()))
.findFirst();
If you want a default value (such as null) when no match is found, use:
Map<String, Object> closedTaxLotByTxnId =
data.values()
.stream()
.filter(m -> m.get(Constants.USER_TRAN_ID).equals(stsTxn.getSeedTrade().getTransactionId()))
.findFirst()
.orElse(null);

Related

Java 8 stream Map<String, Map<String, Integer>> return map values if root map key contains

I have a map of maps:
Map<String, Map<String, Integer>> rootMap
and I want to return the rootMap values Map<String, Integer> if rootMap key contains stringValue using stream.
I tried:
rootMap.entrySet().stream().filter(e -> e.getKey().contains(stringValue)).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
but I get Map<Object, Object> instead of Map<String, Integer>
Update #1
// it's a class with one field and a helper method
// #Data is a Lombok annotation
#Data
public class A {
public Map<String, Map<String, Integer>> rootMap;
public Map<String, Integer> getValuesByKey(String stringValue) {
return rootMap.entrySet().stream().filter(e -> e.getKey().contains(stringValue)).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}
}
Here is your expression:
rootMap.entrySet()
.stream()
.filter(e -> e.getKey().contains(stringValue))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
Here is your goal:
and I want to return the rootMap values Map<String, Integer> if
rootMap key contains stringValue using stream.
Recall that map keys must be unique. You can't have more than one Map.Entry of the same instance with the same key. Therefore, you can obtain the Map<String, Integer> corresponding to the key in rootMap whose value is stringValue as follows:
rootMap.entrySet()
.stream()
.filter(e -> e.getKey().equals(stringValue))
.map(e -> e.getValue())
.findAny()
.get();
To defend against an error in the case that the key does not exist in rootMap you can use this version:
rootMap.entrySet()
.stream()
.filter(e -> e.getKey().equals(stringValue))
.map(e -> e.getValue())
.findAny()
.orElse(Collections.emptyMap());

How to read Specific Map Key Value in case of an Array Object

I have the following Map structure
{empId=1234, empName=Mike, CDetails=[{"collegeName":"Peters Stanford","collegeLoc":"UK","collegeLoc":"UK"}]}
I need to read the value collegeLoc from the above Map
I tried this way , its working , but is there any better way
myMap.entrySet().stream().filter(map -> map.getKey().equals("CDetails")).forEach(e -> {
List<Object> objsList = (List<Object>) e.getValue();
for(int i=0;i<objsList.size();i++)
{
HashMap<String,String> ltr = (HashMap<String, String>) objsList.get(i);
System.out.println(ltr.get("collegeLoc"));
}
});
CDetails is a List, not a Map.
Try this:
empMap.entrySet().stream()
.map(map -> map.get("CDetails"))
.filter(Objects::nonNull)
.flatMap(List::stream)
.map(element -> ((Map)element).get("collegeLoc"))
.filter(Objects::nonNull)
.forEach(System.out::println);

Split entrySet and filter in java 8 using streams

I have an issue with streams
I have a Map<LocalDateTime, Set<Vote>> map = new HashMap<>();
I have to count the number of votes and put it in a new map grouped by localDateTime but I need to count only the vote filtered by Type. I don't know how to do this with a stream.
I have tried this but it doesn't work and it doens't even compile
public Map<LocalDateTime, Integer> numbersOfVotes(TypeVote typeVote) {
return map.entrySet().stream().filter(en -> en.getValue().stream().filter(v -> v.getTypeVote().equals(typeVote)))
.collect(Collectors.toMap(Entry::getKey, e -> e.getValue().size()));
}
Class vote has 2 attributes, name and TypeVote (enum)
public Map<LocalDateTime, Integer> numbersOfVotes(TypeVote typeVote) {
return null;
}
My return value must be Map<LocalDateTime, Integer>.
How to do this using streams in Java 8 ?
final Map<LocalDateTime, Integer> result = map.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey,
(Map.Entry<LocalDateTime, Set<Vote>> entry) -> (int) entry.getValue().stream()
.filter((Vote vote) -> true) // Here insert real filtering
.count()));
something like
Function<Map.Entry<LocalDateTime, Set<Vote>>, Integer> fun = e -> (int) e.getValue()
.stream().filter(vote -> typeVote.equals(vote.getTypeVote()))
.count();
Map<LocalDateTime, Integer> collect = map.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, fun));

List with inner List to Map Java Stream Api

I have a list of elements:
List<OuterElement> outerElements;
OuterElement object has 2 property:
String key;
List<InnerElement> innerElements;
InnerElement object has 1 property:
String value;
I need to create a map where for each innerElement will be created an Entry, where key will be outerElement key, and value will be innerElement value;
Map<String, String> // actually Map<OuterElement.key, InnerElement.value>
How to do it using Stream API?
I have tried something like this, but it doesn't work:
Map<String, String> result = outerElements.stream()
.forEach(outerElement -> outerElement.getInnerElements().stream().collect(Collectors.toMap(OuterElement::getKey, InnerElement::getValue));
In addition to Ruslan answer for java 8 you could use this one:
Map<String, List<String>> collect = elements.stream()
.collect(Collectors.groupingBy(OuterElement::getKey,
Collectors.collectingAndThen(Collectors.toList(), outers -> outers.stream()
.flatMap(o -> o.getInnerElements().stream())
.map(InnerElement::getValue)
.collect(Collectors.toList()))));
if you could use something like MultiValueMap:
MultiValueMap<String, String> map = elements.stream()
.collect(Collectors.groupingBy(OuterElement::getKey,
LinkedMultiValueMap::new,
Collectors.collectingAndThen(Collectors.toList(), outers -> outers.stream()
.flatMap(o -> o.getInnerElements().stream())
.map(InnerElement::getValue)
.collect(Collectors.toList()))));

Could you help me to merge values of several maps?

I'm trying to do the following modification:
final Map<String, List<Map<String, String>>> scopes = scopeService.fetchAndCacheScopesDetails();
final Map<String, Map<String, String>> scopesResponse = scopes.entrySet().stream().collect
(Collectors.toMap(Map.Entry::getKey, e -> e.getValue()
.stream().collect(Collectors.toMap(s -> (String) s.get(SCOPE_NM), s -> (String) s.get(SCOPE_ID))))
);
But I face "Duplicate key" error, so I'd like to change scopeResponses to Map<String, Map<String, List<String>>>
Could you tell me how to merge values s -> (String) s.get(SCOPE_ID) into a List or Set in this situation?
You need to create a Set for the value of the inner Map, and supply a merge function:
final Map<String, Map<String, Set<String>>> scopesResponse = scopes.entrySet().stream().collect
(Collectors.toMap(Map.Entry::getKey, e -> e.getValue()
.stream().collect(Collectors.toMap(s -> s.get(SCOPE_NM),
s -> {Set<String> set= new HashSet<>(); set.add(s.get(SCOPE_ID)); return set;},
(s1,s2)->{s1.addAll(s2);return s1;}))));
Or, you can construct the inner Map with groupingBy:
final Map<String, Map<String, Set<String>>> scopesResponse2 = scopes.entrySet().stream().collect
(Collectors.toMap(Map.Entry::getKey, e -> e.getValue()
.stream().collect(Collectors.groupingBy(s -> s.get(SCOPE_NM),
Collectors.mapping(s -> s.get(SCOPE_ID),Collectors.toSet())))));
You can also do it using Guava's ListMultimap (multimap is like a map of lists):
Map<String, ListMultimap<String, String>> scopesResponse = scopes.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, e -> toMultimap(e)));
where
static ImmutableListMultimap<String, String> toMultimap(
Map.Entry<String, List<Map<String, String>>> entry) {
return entry.getValue().stream().collect(ImmutableListMultimap.toImmutableListMultimap(
s -> (String) s.get(SCOPE_NM),
s -> (String) s.get(SCOPE_ID)
));
}
If the values in the lists turn out to be duplicated, and you don't want that, use SetMultimap instead.

Categories

Resources