Java 绘制河流地图<;T>;到地图<;T、 长期>;那算吗?

Java 绘制河流地图<;T>;到地图<;T、 长期>;那算吗?,java,mapping,java-8,java-stream,Java,Mapping,Java 8,Java Stream,我有一个流,是否可以生成一个映射,将每个元素的计数增加一个?我还想知道它是否可以将T,Long反转为Long,T,然后将其存储在映射中,示例输入/输出: 流的内容示例: 第一个问题需要输出: (kgj, 1) (def, 2) (dgh, 3) 最终想要的输出: (1, kgj) (2, def) (3, dgh) 到目前为止,对于流,我所拥有的: 这将当前将流转换为具有不同元素的流,然后转换为统计发生次数的映射,这不是我想要的,因为我希望它在经过的每个元素上继续计数 有什么方法可以满足我的

我有一个
,是否可以生成一个
映射
,将每个元素的计数增加一个?我还想知道它是否可以将
T,Long
反转为
Long,T
,然后将其存储在
映射中,示例输入/输出:

流的内容示例

第一个问题需要输出:

(kgj, 1)
(def, 2)
(dgh, 3)
最终想要的输出:

(1, kgj)
(2, def)
(3, dgh)
到目前为止,对于
,我所拥有的:

这将当前将
转换为具有不同元素的
,然后转换为统计发生次数的
映射
,这不是我想要的,因为我希望它在经过的每个元素上继续计数


有什么方法可以满足我的要求吗?

您可以编写自己的
收集器,为您计算遇到的元素。类似于以下工作:

  Stream<String> strings = Stream.of("kgj", "def", "dgh");

  strings.distinct().collect(Collector.of(
          HashMap::new,
          (BiConsumer<Map<String, Long>, String>) (map, str) -> {
            map.put(str, Long.valueOf(map.size() + 1));
          },
          (left, right) -> {
            long s = left.size();
            right.entrySet().forEach(e -> left.put(e.getKey(),
                                                   Long.valueOf(
                                                           e.getValue()
                                                                   .longValue()
                                                           + s)));
            return left;
          })).forEach((k, v) -> System.out.println("k = " + k + " / v = " + v));
Stream strings=Stream.of(“kgj”、“def”、“dgh”);
strings.distinct().collect(Collector.of(
HashMap::新建,
(双消费者)(地图、街道)->{
map.put(str,Long.valueOf(map.size()+1));
},
(左,右)->{
长s=左。大小();
right.entrySet().forEach(e->left.put(e.getKey(),
长期价值(
e、 getValue()
.longValue()
+(s);;
左转;
})).forEach((k,v)->System.out.println(“k=“+k+”/v=“+v”);

请注意,(有点复杂)组合器(在并行处理流的情况下需要使用
Collector.of()
的第三个参数)。

受@jpvee的启发,我制作了一个
收集器
,它回答了问题的最后一个子问题,并打算更清楚一些:

public static <T> Collector<T, ?, Map<Long, T>> indexing() {
    return Collector.of(
            HashMap::new,
            (map, t) -> map.put(Long.valueOf(map.size() + 1), t),
            (left, right) -> {
                final long size = left.size();
                right.forEach((k, v) -> left.put(k + size, v));
                return left;
            },
            Collector.Characteristics.CONCURRENT
    );
}
公共静态收集器索引(){
返回收集器(
HashMap::新建,
(map,t)->map.put(Long.valueOf(map.size()+1),t),
(左,右)->{
最终长尺寸=left.size();
右.forEach((k,v)->左.put(k+大小,v));
左转;
},
Collector.Characteristics.CONCURRENT
);
}
它的作用是:

  • 上操作时,它返回一个
    映射
    ,该映射用流的遭遇顺序索引
    T
  • 它使用的是
收集器,它通常接受以下内容:
  • 地图的供应商
  • 映射添加一个元素的累加器
  • 组合两个可能来自并发访问的映射的组合器
  • 一系列特征
因此,我提供的是:

  • Supplier
    :一个新的
    HashMap
  • BiConsumer
    :获取映射并添加新元素的函数
  • BinaryOperator
    :组合两个映射的函数
  • 收集器.characteristics
    :此方法的字符,允许并发执行
@assylias我想说,它提供了一个解决方法,感谢您指导我回答这个问题,但是它不是一个确定的答案,因此我认为您为什么将它作为一个评论发布。当使用重复输入(例如[“abc”、“def”、“abc”])时,您希望第一个问题的输出是什么?@jpvee它应该只计算不同的元素,(到目前为止,我已经有了这一点),对于streams,很容易通过
list.stream().distinct()
获得一个稳定的distinct。在scala中,我只需要
x.zipWithIndex
和第二个:
x.zipWithIndex.map(x=>(x.\u 2,x.\u 1))
这会对性能造成什么影响?有没有办法“禁用”并行处理,因为你永远无法并行计算……或者你可以?收集器的一种有趣用法,但最终是O(n log n)及时。原因是每次合并只复制一半的元素,并且合并树中有logn级别。这可以并行运行,但足够大的n将淹没任何并行加速。
  Stream<String> strings = Stream.of("kgj", "def", "dgh");

  strings.distinct().collect(Collector.of(
          HashMap::new,
          (BiConsumer<Map<String, Long>, String>) (map, str) -> {
            map.put(str, Long.valueOf(map.size() + 1));
          },
          (left, right) -> {
            long s = left.size();
            right.entrySet().forEach(e -> left.put(e.getKey(),
                                                   Long.valueOf(
                                                           e.getValue()
                                                                   .longValue()
                                                           + s)));
            return left;
          })).forEach((k, v) -> System.out.println("k = " + k + " / v = " + v));
public static <T> Collector<T, ?, Map<Long, T>> indexing() {
    return Collector.of(
            HashMap::new,
            (map, t) -> map.put(Long.valueOf(map.size() + 1), t),
            (left, right) -> {
                final long size = left.size();
                right.forEach((k, v) -> left.put(k + size, v));
                return left;
            },
            Collector.Characteristics.CONCURRENT
    );
}