番石榴:如何定制减少多图?

时间:2015-10-19 12:56:56

标签: java guava

reduce 的概念是否在Guava库中实现?我的意思是我有一个多图:

[1] -> 1, 2, 5, 8
[2] -> 3, 6, 4
[3] -> 1, 0

然后我有一个乘法函数

(a, b) -> a * b

我想得到以下地图:

[1] -> 80          // 1 * 2 * 5 * 8
[2] -> 72          // 3 * 6 * 4
[3] -> 0           // 1 * 0

我如何在番石榴中做到这一点?

3 个答案:

答案 0 :(得分:5)

我不认为番石榴有减少操作。我猜你有两个选择。

如果您正在使用,只需在条目集上流式传输,然后将条目收集到包含groupingByreduce的新地图中。

import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.mapping;
import static java.util.stream.Collectors.reducing;

...

Map<Integer, Integer> map = 
    multimap.entries()
            .stream()
            .collect(groupingBy(Map.Entry::getKey,
                                reducing(1, Map.Entry::getValue, (a, b) -> a * b)));
您可以猜测,

groupingBy会根据键值对条目进行分组。然后我们只是通过首先将它们映射到它们的值并最后将它们相乘来减少分组的值(Entry<Integer, Integer>) - 为乘法提供1的标识值。

<小时/> 如果您无法使用,则可以使用Map<Integer, Collection<Integer>>Multimap取回Multimaps.asMap并使用Maps.transformValues

Map<Integer, Collection<Integer>> tempMap = Multimaps.asMap(oldMap);
Map<Integer, Integer> newMap = 
    Maps.transformValues(tempMap, new Function<Collection<Integer>, Integer>() {
            @Nullable
            @Override
            public Integer apply(Collection<Integer> input) {
                //do the multiplication here
                return 0;
            }
        });

答案 1 :(得分:1)

使用String键和List<Integer>作为值。

您也可以尝试类似

的内容
    Map<String, List<Integer>> test = new HashMap<String, List<Integer>>();
    test.put("a", Lists.newArrayList(1, 2, 3));
    test.put("b", Lists.newArrayList(4, 5, 6));

    Map<String, Integer> transformEntries = Maps.transformEntries(test, new EntryTransformer<String, List<Integer>, Integer>() {

        @Override
        public Integer transformEntry(String key, List<Integer> values) {
            Integer a = 1;
            for (Integer value : values) {
                a = value * a;
            }
            return a;
        }
    });

    System.out.println(transformEntries);

结果: {a = 6,b = 120}

Maps.EntryTransformer

答案 2 :(得分:0)

最简单的方法就是使用entries()上的流,并在其上映射一个函数,将函数转换为流并在其上运行合适的reduce()函数。

这样的事情:

HashMap<Integer, Integer> collected =
    mmap.entries().stream().collect(HashMap::new,
            (map, e) -> {
                map.put(e.getKey(), e.getValue().stream().reduce((a, b) -> (a * b)).get());
            }, HashMap::putAll);