Newbie Programmer
Newbie Programmer

Reputation: 61

How to filter a HashMap with a value Predicate?

I have the following query header method:

public Map<String, List<String>> query(Predicate<String> valuePredicate)

Before this, I implementated another method with a specific column (label). It was:

public Map<String, List<String>> query(String keySelector,Predicate<String> valuePredicate) {
        try {
            final List<String> row = frameInfo.get(keySelector);
            List<Integer> indices = IntStream.range(0, row.size()).filter(columnIndex -> valuePredicate.test(row.get(columnIndex))).boxed().collect(Collectors.toList());
            Map<String, List<String>> auxMap = new HashMap<>();
            for (Map.Entry<String, List<String>> entry : frameInfo.entrySet()) {
                for (int columnIndex : indices) {
                    auxMap.putIfAbsent(entry.getKey(), new ArrayList<>());
                    auxMap.get(entry.getKey()).add(entry.getValue().get(columnIndex));
                }
            }
            return auxMap;
        }catch (Exception e){
            return null;
        }

How could I implementate the new method with just 1 argument (valuePredicate)?

Upvotes: 2

Views: 2312

Answers (1)

WJS
WJS

Reputation: 40034

It seems to me that you could do it like so. Since the predicate tests a string from a list which can be streamed, I don't see why you need to iterate the indices.

  • Stream the entrySet from frameInfo
  • then flatmap e.getValue() (a list) and apply the predicate
  • preserve the key and filtered value in a String array
  • then group based on the key
public Map<String, List<String>> queryAll(Predicate<String> valuePredicate) {
    return frameInfo.entrySet().stream()
            .flatMap(e -> e.getValue().stream()
                    .filter(valuePredicate)
                    .map(s -> new String[] { e.getKey(), s }))
            .collect(Collectors.groupingBy(arr -> arr[0],
                    Collectors.mapping(arr -> arr[1],
                            Collectors.toList())));
}

I'm tossing this one in as well, it's a rewrite of your existing method.

  • it simply streams the list for the supplied key, applies the filter and populates the map. Since there is only one key, you could just return a list.
public Map<String, List<String>> query(String keySelector,
        Predicate<String> valuePredicate) {
    return frameInfo.get(keySelector).stream()
            .filter(valuePredicate)
            .collect(Collectors.groupingBy(a -> keySelector));
}

If I misunderstood something, let me know and I will try to correct it.

Upvotes: 2

Related Questions