当前位置: 首页 > 面试题库 >

使用AtomicInteger在Stream中建立索引是否合法?

罗翔
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表达式中使用了有效的最终变量或最终变量约束,因此使用受到限制。我必须使用数组及其第一个也是唯一索引的解决方法,这是我的问题“
如何在JavaStream中增加值”的第一个注释中建议的。这是示例:

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(" "));

不管它看起来多么丑陋,我都要求描述可能的弱点及其原因。我不在乎性能,但在意第二种解决方案的设计和可能的弱点。

请不要将AtomicInteger与多线程问题匹配。我使用该类是因为它以本例所需要的方式接收,递增和存储值。

正如我在回答中经常说的那样, “ Java Stream-API”
并不是万能的。我的目标是探索并找出这句话的适用范围,因为与StringBuilder的代码段相比,我发现最后一个代码段非常清晰,可读且简短。

编辑:在使用Stream-API进行迭代时需要同时使用项目和索引时,是否存在任何适用于上述摘录以及所有问题的替代方法?


问题答案:

该软件包的文档java.util.stream指出:

通常,不鼓励行为参数对流操作的副作用,因为它们经常会导致无意识地违反无状态要求以及其他线程安全危害。

[…]

副作用的顺序可能令人惊讶。即使将管道约束为产生与流源的遇到顺序一致的结果(例如,IntStream.range(0,5).parallel().map(x -> x*2).toArray()必须产生[0, 2, 4, 6, 8]),也无法保证将mapper函数应用于单个元素的顺序或给指定元素执行任何行为参数的线程。

这意味着可能会无序地处理元素,因此Stream-solutions可能会产生错误的结果。

这(至少对我而言)是针对您的两个Stream解决方案的致命论点。

通过消除的过程,我们只剩下“传统解决方案”了。老实说,我认为此解决方案没有任何问题。如果要摆脱for-loop,可以使用foreach-loop
重写此代码:

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

要获得简化的(据我所知)正确的解决方案,请查看Octavian
R.的答案。

您的问题。“流量限制”是基于意见的。

问题的答案到此结束。其余的是我的观点,应视为这样。

在Octavian
R.的解决方案中,通过创建了一个人工索引集IntStream,然后将其用于访问String[]。对我来说,这比简单的for-或-
foreach循环具有更高的认知复杂度,在这种情况下,我认为使用流而不是循环没有任何好处。



 类似资料:
  • 当想要使用java-stream时,由于lambda表达式中使用了有效的final或final变量约束,使用受到限制。我必须使用使用数组及其第一个也是唯一的索引的变通方法,这是在我的问题如何在Java流中增加一个值的第一个注释中建议的。下面是示例: 是的,这是一个糟糕的解决方案,我没有听到什么好的理由隐藏在一个我找不到的问题的评论中(如果你提醒我其中的一些,如果可能的话,我会投两次票)。但是,如果

  • 本文向大家介绍如何在SAP中建立表索引?,包括了如何在SAP中建立表索引?的使用技巧和注意事项,需要的朋友参考一下 您需要使用事务SE11。此事务用于在表上创建索引。 在这里要牢记的一件事是将这些索引转移到生产中。您需要使用事务在开发环境中创建索引。创建它们后,您需要将它们传输到生产环境。 进行更改后,激活表格。

  • 问题内容: 我有一个清单说。我想为每个唯一值分配一个特定的“索引”来获取。 这是我的代码: 事实证明这很慢。 具有1M个元素和100K个唯一元素。我也尝试过用lambda和sort进行地图操作,这没有帮助。这样做的理想方法是什么? 问题答案: 由于执行线性搜索,然后对中的每个元素执行线性搜索,因此导致代码变慢。因此,对于每1M个项目,您要进行(最多)100K个比较。 将一个值转换为另一个值的最快方

  • 问题内容: 我正在使用索引器将数据从我的SQL数据库同步到Azure搜索服务。我的SQL视图中有一个字段,其中包含XML数据。列包含字符串列表。集合(Edm.String)中我的Azure搜索服务索引中的对应字段。在检查一些文档时,我发现Indexer不会将Xml(SQL)更改为Collection(Azure Search)。关于如何从Xml数据创建Collection的方法,是否有任何解决方法

  • 区分度不高的字段不适合做索引,因为索引页是需要有开销的,需要存储的,不过这类字段可以做联合索引的一部分。