Home > OS >  java 8 map.get multiple key values
java 8 map.get multiple key values

Time:07-08

I have following code where I want to get value for multiple keys which starts with same name: for example contents_of_a1, contents_of_ab2, contents_of_abc3

Optional.ofNullable(((Map<?, ?>) fieldValue))
                    .filter(Objects::nonNull)
                    .map(coverages -> coverages.get("contents_of_%"))
                    .filter(Objects::nonNull)
                    .filter(LinkedHashMap.class::isInstance)
                    .map(LinkedHashMap.class::cast)
                    .map(contents -> contents.get("limit"))
                    .map(limit -> new BigDecimal(String.valueOf(limit)))
                    .orElse(new BigDecimal(number));

How can I pass contents_of%

CodePudding user response:

I don't know the reasons behind the data structure and what you want to achieve.

However, it is not important as this can be easily reproduced.

Using of Optional is a good start, however, for iterating and processing multiple inputs, you need to use instead and then Optional inside of collecting (I assume you want Map<String, BigDecimal output, but it can be adjusted easily).

Also, note .filter(Objects::nonNull) is meaningless as Optional handles null internally and is never passed to the next method.

final Map<String, Map<?, ?>> fieldValue = Map.of(
    "contents_of_a", new LinkedHashMap<>(Map.of("limit", "10")),
    "contents_of_b", new HashMap<>(Map.of("limit", "11")),         // Different
    "contents_of_c", new LinkedHashMap<>(Map.of("amount", "12")),  // No amount
    "contents_of_d", new LinkedHashMap<>(Map.of("limit", "13")));

final List<String> contents = List.of(
        "contents_of_a", 
        "contents_of_b", 
        "contents_of_c",
        // d is missing, e is requested instead
        "contents_of_e");

final int number = -1;

final Map<String, BigDecimal> resultMap = contents.stream()
        .collect(Collectors.toMap(
                Function.identity(),                               // key
                content -> Optional.of(fieldValue)                 // value
                        .map(coverages -> fieldValue.get(content))
                        .filter(LinkedHashMap.class::isInstance)
                         // casting here to LinkedHashMap is not required
                         // unless its specific methods are to be used
                         // but we only get a value using Map#get
                        .map(map -> map.get("limit"))
                        .map(String::valueOf)
                        .map(BigDecimal::new)
                         // prefer this over orElse as Optional#orElseGet 
                         // does not create an object if not required
                        .orElseGet(() -> new BigDecimal(number))));

// check out the output below the code
resultMap.forEach((k, v) -> System.out.println(k   " -> "   v));

Only the content for a is used as the remaining were either not an instance of LinkedHashMap, didn't contain a key limit or were not among requested contents.

contents_of_a -> 10
contents_of_b -> -1
contents_of_e -> -1
contents_of_c -> -1

CodePudding user response:

If you want to filter a map for which key starting with "contents_of_", you can do this for Java 8:

Map<String, Object> filteredFieldValue = fieldValue.entrySet().stream().filter(c -> {
    String k = c.getKey();
    return Stream.of("contents_of_").anyMatch(k::startsWith);
}).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
  • Related