java - 惯用地枚举 Java 8 中的对象流

标签 java java-8 java-stream enumeration

一个人如何能惯用地枚举一个 Stream<T>每个映射 T使用 Java 8 流方法实例化为唯一整数(例如,对于数组 T[] values,创建一个 Map<T,Integer>,其中 Map.get(values[i]) == i 的计算结果为 true)?

目前,我正在定义一个递增 int 的匿名类与 Collectors.toMap(..) 一起使用的字段方法:

private static <T> Map<T, Integer> createIdMap(final Stream<T> values) {
    return values.collect(Collectors.toMap(Function.identity(), new Function<T, Integer>() {

        private int nextId = 0;

        @Override
        public Integer apply(final T t) {
            return nextId++;
        }

    }));
}

但是,有没有更简洁/优雅的方式使用 Java 8 流 API 来做到这一点? — 如果可以安全地并行化,则加分。

最佳答案

如果存在重复元素,您的方法将失败。

除此之外,您的任务需要可变状态,因此可以用 Mutable reduction 解决.当我们填充 map 时,我们可以简单地使用 map 的大小来获取未使用的 ID。

比较棘手的部分是合并操作。以下操作只是重复正确 map 的分配,这将处理潜在的重复项。

private static <T> Map<T, Integer> createIdMap(Stream<T> values) {
    return values.collect(HashMap::new, (m,t) -> m.putIfAbsent(t,m.size()),
        (m1,m2) -> {
            if(m1.isEmpty()) m1.putAll(m2);
            else m2.keySet().forEach(t -> m1.putIfAbsent(t, m1.size()));
        });
}

如果我们依赖唯一元素,或者插入一个显式的distinct(),我们可以使用

private static <T> Map<T, Integer> createIdMap(Stream<T> values) {
    return values.distinct().collect(HashMap::new, (m,t) -> m.put(t,m.size()),
        (m1,m2) -> { int leftSize=m1.size();
            if(leftSize==0) m1.putAll(m2);
            else m2.forEach((t,id) -> m1.put(t, leftSize+id));
        });

}

关于java - 惯用地枚举 Java 8 中的对象流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42228539/

相关文章:

java - 退出主 list 时出现错误 :Validation failed,,并且属性在 AndroidManifest.xml 中使用-feature#20000@glEsVersion

java - 计算 JVM 的已用内存

java - Hibernate 可以将列的子集映射到内部子 Pojo 中

java - 每个有状态的中间 Stream API 操作都保证一个新的源集合吗?

Java计算两个ArrayList或HashMap的队列

java 8 stream finde MIN/MAX 限制

java - Spring Webflow - 决策状态与 Action 状态

java - 如何使用内部列表流式传输列表

java - 在单行中调用 Optional#isPresent() 被报告为未调用

java - 为什么java流 "reduce()"累积相同的对象