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");