Java 8 lambda:将Collection转换为元素的Map,迭代位置

dan*_*ial 9 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) {
        map.put(s, pos++);
    }
Run Code Online (Sandbox Code Playgroud)

mab*_*aba 6

它不需要并行流,您可以使用地图的长度作为索引计数器:

collection.stream().forEach(i -> map.put(i, map.size() + 1));
Run Code Online (Sandbox Code Playgroud)

  • 这是一个糟糕的解决方案,我担心:它不是线程安全的,因为不同的线程可能会处理不同的元素,即使是在顺序流上也是如此.另外(不太重要)forEach不保证维持秩序. (3认同)

Stu*_*rks 6

这是一种方法:

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));
Run Code Online (Sandbox Code Playgroud)

不一定是单行或短于简单的循环,但如果你改变toMap到它,它确实使用并行流toConcurrentMap.

另请注意,这假设您有一个随机访问列表,而不是一般Collection.如果你有一个Collection你不能做任何假设的事情,除了按顺序迭代它并增加一个计数器之外你没有什么可做的.

UPDATE

OP已澄清输入是a Collection而不是a,List因此上述不适用.似乎我们对输入的假设很少Collection.OP已指定迭代顺序.使用顺序迭代器,元素将以某种顺序出现,但不能保证它.它可能会在不同的运行之间发生变化,甚至从一次迭代变为另一次迭代(尽管这在实践中是不寻常的 - 除非底层集合被修改).

如果需要保留精确的迭代顺序,我不相信有一种方法可以将其保留到结果中Map而不会Collection顺序迭代输入.

但是,如果确切的迭代顺序并不重要,并且要求输出Map具有每个输入元素的唯一值,那么可以并行执行类似的操作:

Collection<String> col = apiCall();
Iterator<String> iter = col.iterator();

Map<String, Integer> map =
    IntStream.range(0, col.size())
        .parallel()
        .boxed()
        .collect(toConcurrentMap(i -> { synchronized (iter) { return iter.next(); }},
                                 i -> i));
Run Code Online (Sandbox Code Playgroud)

现在这远远不是单行.我也不清楚它有多有用.:-)但它确实表明可以并行执行类似的操作.请注意,我们必须同步访问输入集合的迭代器,因为它将从多个线程调用.另请注意,这是迭代器的一种不寻常的用法,因为我们从不调用,hasNext并且我们假设next完全调用输入集合返回的次数是安全的size().


Sya*_*m S 0

尝试

    int[] pos = { 0 };
    list.forEach( a -> map.put(a, pos[0]++));
Run Code Online (Sandbox Code Playgroud)

  • 您怎么知道该集合没有使用并行蒸汽? (2认同)
  • @SyamS:这同样适用于 `Iterator.forEach`,正如 javadoc 中的这句话所阐明的:“**除非实现类另有指定**,操作按照迭代的顺序执行”。这句话告诉你执行的顺序可能和迭代器中的不一样。而且问题并没有说明使用什么样的集合。 (2认同)