当前位置: 首页 > 知识库问答 >
问题:

在流中使用AtomicInteger进行索引是合法的吗?

蓬弘
2023-03-14
String sentence = "Hi, this is just a simple short sentence";
String[] split = sentence.split(" ");
StringBuilder stringBuilder = new StringBuilder();
for (int i=0; i<split.length; i++) {
    if (i%2==0) {
        stringBuilder.append(split[i]);
    } else {
        stringBuilder.append(split[i].toUpperCase());
    }
    if (i<split.length-1) { stringBuilder.append(" "); }
}

当想要使用java-stream时,由于lambda表达式中使用了有效的final或final变量约束,使用受到限制。我必须使用使用数组及其第一个也是唯一的索引的变通方法,这是在我的问题如何在Java流中增加一个值的第一个注释中建议的。下面是示例:

int index[] = {0};
String result = Arrays.stream(split)
    .map(i -> index[0]++%2==0 ? i : i.toUpperCase())
    .collect(Collectors.joining(" "));

是的,这是一个糟糕的解决方案,我没有听到什么好的理由隐藏在一个我找不到的问题的评论中(如果你提醒我其中的一些,如果可能的话,我会投两次票)。但是,如果我使用AtomicInteger呢--它有什么区别吗?与前一种相比,它是一种好的、安全的、没有副作用的方式吗?

AtomicInteger atom = new AtomicInteger(0);
String result = Arrays.stream(split)
    .map(i -> atom.getAndIncrement()%2==0 ? i : i.toUpperCase())
    .collect(Collectors.joining(" "));

不管它对任何人来说有多难看,我要求描述可能的弱点及其原因。我不关心性能,但设计和可能的弱点的第二个解决方案。

正如我在回答问题时经常说的,“Java Stream-API”并不是万能的。我的目标是探索并找到这句话适用的边缘,因为我发现与StringBuilder的代码段相比,最后一个代码段非常清晰、易读和简短。

编辑:在使用Stream-API进行迭代时,当需要同时处理item和index时,是否有任何可供选择的方法适用于上面的代码段和所有问题?

共有1个答案

夹谷岳
2023-03-14

java.util.Stream包的文档说明:

流操作的行为参数中的副作用通常是不鼓励的,因为它们常常会导致无意中违反无国籍要求,以及其他线程安全隐患。

[...]

boolean toUpper = false; // 1st String is not capitalized
for (String word : splits) {
    stringBuilder.append(toUpper ? word.toUpperCase() : word);
    toUpper = !toUpper;
}

对于一个精简的和(据我所知)正确的解决方案,看看屋大维R.的答案。

你的问题。“溪流的界限”是基于意见的。

问题的答案到此为止。剩下的都是我的意见,应该算是这样。

 类似资料:
  • 问题内容: 我想得到一个答案,指出为什么以下在一个非常简单的示例上描述的想法通常被认为是不好的并且知道它的缺点的原因。 我有一句话,我的目标是使每一秒都变成大写。对于这两种情况,我的出发点是完全相同的: 在 传统 和程序的做法是: 当要使用java-stream时,由于在lambda表达式中使用了有效的最终变量或最终变量约束,因此使用受到限制。我必须使用数组及其第一个也是唯一索引的解决方法,这是我

  • 问题内容: 假设我要实现一个非常简单的类,并且要注意并发和多线程问题, 即使是以下方法,还是要这样做吗? 另一方面,如果我们将所有方法都同步了,就不会再使用了,对吗? 问题答案: 将您的金额声明为不会阻止线程在方法执行过程中被抢占(如果未同步)。因此,举例来说,如果您的方法没有以任何方式同步,即使您的方法数量达到 这些问题称为比赛条件。一个可能的示例是,当两个线程尝试从同一帐户转移资金时。当一个线

  • 问题内容: 如果排序列上有索引,排序是否使用mysql索引?索引还用于其他什么用途? 它对列的组合索引和单独索引有什么区别? 问题答案: 是的,当按排序列排序时,MySQL使用索引对信息进行排序。 另外,如果在添加到 SELECT 子句的所有列中都有索引,则MySQL不会从表本身加载数据,而是从索引加载数据(更快)。 合并和单独的索引之间的区别是,MySQL不能使用超过 一个 每次查询索引,因此,

  • 问题内容: 我有两个具有以下映射的索引(我将简化它们的映射): 1)AccountType映射: 2)ProductType映射: 现在,我有几件事需要弄清楚: 1)首先,有一个索引是一个好主意,在我的情况下是帐户,并且产品是嵌套对象,但是在这里每次我要更新/添加新产品时,我都必须重新索引(更新)整个帐户文件? 2)我的第二个问题是:我想具有搜索功能,因此,如果用户通过在文本框中键入内容进行搜索,

  • 问题内容: 我有两个数组:墙和邻居。 我有一个枚举: 现在,我希望能够按其方向访问墙壁或邻居,因此不必绕过一堆魔术索引。 但是,当我阅读Enum.ordinal()的文档时,它说程序员几乎不会使用此方法,这使我认为不应以这种方式使用它。 我正在考虑做类似的事情: 甚至: 我应该恢复对索引值设置为NORTH,SOUTH,EAST,WEST的静态常量还是使用Enum的序数方法? 问题答案: 在切线问题

  • 我有以下两种调用集合操作的形式,都返回相同的结果,但我仍然不能完全依赖于方法引用,需要一个lambda。 为此,考虑以下由100个随机数组成的流 1) 以下示例使用纯lambda 2) 以下尝试使用方法引用,但第二个参数仍然需要lambda 在本例中,如何重写java 8中collect方法的第二个参数以使用方法引用而不是lambda?