【问题标题】:How to update each element in a List in Java 8 using Stream API如何使用 Stream API 在 Java 8 中更新列表中的每个元素
【发布时间】:2018-01-05 09:23:28
【问题描述】:

我有一个定义如下的列表:

List<Integer> list1 = new ArrayList<>();
list1.add(1); 
list1.add(2);

如何在不创建新列表的情况下使用 Java 8 的 Stream API 将列表的每个元素加一(即以列表 [2,3] 结尾)?

【问题讨论】:

  • 为什么不想创建一个新列表?
  • @ifly6 例如,您可能有一个预期会通过副作用起作用的方法。
  • 简单,使用.map() 进行任何操作。见@bentaye 答案
  • 投反对票:缺乏研究
  • 赞成:好问题

标签: java java-8 java-stream


【解决方案1】:

当您从List 创建Stream 时,您不能根据“Non-interference” section of the package documentation 中的指定从Stream 修改源List。不遵守此约束可能会导致ConcurrentModificationException,或者更糟糕的是,数据结构损坏而不会出现异常。

使用 Java Stream 直接操作列表的唯一解决方案是创建一个不迭代列表本身的 Stream,即迭代索引之类的流

IntStream.range(0, list1.size()).forEach(ix -> list1.set(ix, list1.get(ix)+1));

点赞Eran’s answer

但这里没有必要使用Stream。目标可以很简单地实现

list1.replaceAll(i -> i + 1);

这是在 Java 8 中引入的a new List method,也允许顺利使用 lambda 表达式。除此之外,还有可能众所周知的Iterable.forEach、不错的Collection.removeIf 和就地List.sort 方法,以命名其他不涉及Stream API 的新Collection 操作。此外,Map 接口还有几个值得了解的新方法。

另见官方文档中的“New and Enhanced APIs That Take Advantage of Lambda Expressions and Streams in Java SE 8”。

【讨论】:

    【解决方案2】:

    Holger's answer 几乎完美。但是,如果您担心整数溢出,则可以使用 Java 8 中发布的另一种实用方法:Math#incrementExact。如果结果溢出int,这将抛出ArithmeticException。方法引用也可以用于此,如下所示:

    list1.replaceAll(Math::incrementExact);
    

    【讨论】:

      【解决方案3】:

      您可以通过 IntStream 结合 forEach 来迭代索引:

      IntStream.range(0,list1.size()).forEach(i->list1.set(i,list1.get(i)+1));
      

      不过,这与普通的 for 循环没有太大区别,而且可能可读性较差。

      【讨论】:

        【解决方案4】:

        将结果重新分配给list1

        list1 = list1.stream().map(i -> i+1).collect(Collectors.toList());
        

        【讨论】:

        • 从 OP “不创建新列表”。您正在创建一个新列表。
        • 公平地说,不清楚他是指new variablenew object 之类的新列表。
        【解决方案5】:
        public static Function<Map<String, LinkedList<Long>>, Map<String, LinkedList<Long>>> applyDiscount = (
        
                    objectOfMAp) -> {
        
        
                objectOfMAp.values().forEach(listfLong -> {
        
        
                    LongStream.range(0, ((LinkedList<Long>) listfLong).size()).forEach(index -> {
        
                        Integer position = (int) index;
        
                        Double l = listfLong.get(position) - (10.0 / 100 * listfLong.get(position));
        
                        listfLong.set(position, l.longValue());
        
                    });
        
                });
        
                return objectOfMAp;
        
            };
        

        【讨论】:

          猜你喜欢
          • 2022-08-17
          • 1970-01-01
          • 2022-11-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-08-24
          • 2017-09-26
          相关资源
          最近更新 更多