Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/python-2.7/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java8Lambda:将集合转换为元素、迭代位置的映射_Java_Lambda_Java 8_Java Stream - Fatal编程技术网

Java8Lambda:将集合转换为元素、迭代位置的映射

Java8Lambda:将集合转换为元素、迭代位置的映射,java,lambda,java-8,java-stream,Java,Lambda,Java 8,Java Stream,如何将像[“a”,“b”,“c”]这样的集合转换为像{“a”:0,“b”:1,“c”:2}这样的映射,值是迭代的顺序。 JDK8中是否有一个包含流和收集器的单行程序? 旧的方式是这样的: Collection<String> col = apiCall(); Map<String, Integer> map = new HashMap<>(); int pos = 0; for (String s : collection) {

如何将像[“a”,“b”,“c”]这样的集合转换为像{“a”:0,“b”:1,“c”:2}这样的映射,值是迭代的顺序。 JDK8中是否有一个包含流和收集器的单行程序? 旧的方式是这样的:

    Collection<String> col = apiCall();
    Map<String, Integer> map = new HashMap<>();
    int pos = 0;
    for (String s : collection) {
        map.put(s, pos++);
    }
Collection col=apiCall();
Map Map=newhashmap();
int pos=0;
用于(字符串s:集合){
map.put(s,pos++);
}
试试看


如果不需要并行流,则可以使用映射的长度作为索引计数器:

collection.stream().forEach(i -> map.put(i, map.size() + 1));
以下是一种方法:

List<String> list = Arrays.asList("a", "b", "c");

Map<String, Integer> map =
    IntStream.range(0, list.size())
        .boxed()
        .collect(toMap(i -> list.get(i), i -> i));
现在,这远非一艘班轮。我也不清楚它有多有用。:-)但它确实证明了类似这样的并行操作是可能的。注意,我们必须同步对输入集合迭代器的访问,因为它将从多个线程调用。还要注意,这是迭代器的一个不寻常的用法,因为我们从不调用
hasNext
,并且我们假设调用
next
是安全的,根据一般解决方案,输入集合的
size()

返回的次数正好是:

collection.stream().forEachOrdered(i -> map.put(i, map.size()));
从:

此操作一次处理一个元素,如果存在元素,则按遭遇顺序处理

这里重要的一点是,如果有,它会保留顺序,例如
集合
分类数据集
列表
。这样的流称为有序流(不要与排序流混淆)。它可以通过不同的线程调用使用者方法,但始终确保“一次一个”和线程安全保证

当然,如果流是并行的,它将不会从并行执行中受益


为完整起见,以下解决方案即使在使用并行处理的并行流上也能起作用,如果它们仍然是有序的:


如果您不介意使用第三方库,“我的库”具有所有类型的扩展,并附加了大量功能强大的操作,因此您可以这样实现:-

    CollectionX<String> col = CollectionX.fromCollection(orgCol);
    col.zipWithIndex()
       .toMap(k->k.v1, v->v.v2);

您可以使用AtomicInteger作为流中的索引:

    Collection col = Arrays.asList("a", "b", "c");
    AtomicInteger index = new AtomicInteger(0);
    Map collectedMap =  col.stream().collect(Collectors.toMap(Function.identity(), el -> index.getAndIncrement()));
    System.out.println("collectedMap = " + collectedMap);

请注意,您的代码将创建映射图
{“a”:0,“b”:1,“c”:2}
,目前的答案如下。您可能对@ajb感兴趣,谢谢,更新了问题“您如何知道集合不使用并行steam?”@fabian:我不理解这个问题?@fabian a
Stream
似乎不涉及此问题。流不是必需的,只在单个线程上运行。因此,在流上使用
forEach
可能会导致并行执行lambda表达式。@SyamS:Iterator.forEach也是如此,正如javadoc中的这句话所阐明的:“除非实现类另有规定,否则操作是按迭代顺序执行的”。这句话告诉您执行顺序可能与迭代器中的不同。问题不在于使用什么样的收藏品,我有一个收藏品。我知道这个列表的解决方案。@danial抱歉,我假设了一个
列表
。谢谢你的澄清。我已将答案更新为仅处理
集合
。您可能会发现它有用,也可能不会有用。:-)
i->i
可以被
Function.identity()
替换。恐怕这是一个糟糕的解决方案:它不是线程安全的,因为不同的元素可能由不同的线程处理,即使是在顺序流上。另外(不太重要的)forEach也不能保证维持秩序。@Maurice Naftalin:“顺序”是“平行”的反义词。可能你的意思是“有序”,它仍然可以是平行的。@Holger抱歉,我删除了你回复的评论,混淆了这个主题,因为我想修改它。对于阅读本文的人来说,我所说的是:“不,我是指我所说的:“即使在顺序流上”。java.util.stream的文档(在“副作用”下)说:“即使管道被限制生成与流源的遭遇顺序一致的结果,也不能保证。。。对于给定的元素,任何行为参数执行的线程是什么。”@Holger我删除的注释的问题是它是正确的,但不适用;我提到的短语记录了中间操作的行为。这里我需要的文档是针对
forEach
:“对于任何给定的元素,该操作可以在库选择的任何时间和线程中执行。如果操作访问共享状态,它将负责提供所需的同步。”因此,此解决方案不是线程安全的。(
forEachOrdered
不会遇到相同的问题,因此下面的解决方案有效)@Maurice Naftalin:那么我们可以删除评论。关于
forEach
,我不确定引用的句子是否仍然属于前一句,前一句以“For parallel stream pipeline”开头。
stream.collect(HashMap::new, (m, i) -> m.put(i, m.size()),
  (a, b) -> {int offset = a.size(); b.forEach((k, v) -> a.put(k, v + offset));});
    CollectionX<String> col = CollectionX.fromCollection(orgCol);
    col.zipWithIndex()
       .toMap(k->k.v1, v->v.v2);
    ReactiveSeq.fromCollection(col)
               .zipWithIndex()
               .toMap(k->k.v1, v->v.v2);

    Collection col = Arrays.asList("a", "b", "c");
    AtomicInteger index = new AtomicInteger(0);
    Map collectedMap =  col.stream().collect(Collectors.toMap(Function.identity(), el -> index.getAndIncrement()));
    System.out.println("collectedMap = " + collectedMap);