Home > other >  Java Stream fill map from two lists by first list items
Java Stream fill map from two lists by first list items

Time:12-24

I have two lists that I need to check that every product (from products) has a code (from productCodes)

List<String> productCodes = List.of("X_14_AA_85", "X_14_BB_85", "X_14_ZZ_85");
List<String> products = List.of("AA", "BB", "CC", "ZZ");

// I want to achieve a collection of (product code, product)
// according if product name exists in productCode name

// key - product code, value - product
Map<String, String> = Map.of(
  "AA", "X_14_AA_85",
  "BB", "X_14_BB_85",
  "CC", null,
  "ZZ", "X_14_ZZ_85"                 // null if code doesn't exist
);

// after a filter with null keys I could return a message something like this
// List<String> nullableProducts = List.of("CC");
// return "I could prompt that there's no code for product/s: "   nullableProducts;

Is there a way with streams to filter by list item values?

CodePudding user response:

If the purpose is to get a map containing null value, this has to be implemented using a custom collector, because existing implementation throws NullPointerException when putting null:

List<String> productCodes = List.of("X_14_AA_85", "X_14_BB_85", "X_14_ZZ_85");
List<String> products = List.of("AA", "BB", "CC", "ZZ");

Map<String, String> mapCodes = products.stream()
    .distinct()
    .collect(
        HashMap::new, 
        (m, p) -> m.put(p, productCodes
            .stream()
            .filter(pc -> pc.contains(p))
            .findFirst()
            .orElse(null)
        ), 
        HashMap::putAll
    );

System.out.println(mapCodes);

Output:

{AA=X_14_AA_85, BB=X_14_BB_85, CC=null, ZZ=X_14_ZZ_85}

Then the list of non-matched products may be retrieved as follows:

List<String> nonMatchedProducts = mapCodes.entrySet()
    .stream()
    .filter(e -> e.getValue() == null)
    .map(Map.Entry::getKey)
    .collect(Collectors.toList());
System.out.println(nonMatchedProducts);

Output:

[CC]

CodePudding user response:

You can stream the keySet and filter null values:

Java 16 :

List<String> list = map.keySet().stream()
        .filter(key -> map.get(key) == null).toList();

Java 15 and older:

List<String> list = map.keySet().stream()
        .filter(key -> map.get(key) == null)
        .collect(Collectors.toList());

Note: You can't instantiate an unmodifiable Map using Map.of() with null keys or values. Instead, you can do:

Map<String, String> map = new HashMap<>();
map.put("AA", "X_14_AA_85");
map.put("BB", "X_14_BB_85");
map.put("CC", null);
map.put("ZZ", "X_14_ZZ_85");
  • Related