【问题标题】:Execute arithmetic operation on concat String with Java Streams使用 Java Streams 对 concat String 执行算术运算
【发布时间】:2018-11-07 09:34:46
【问题描述】:

大家好,谢谢大家的帮助。

我有一个Stream<String>,其中一个字符串可以是“1+5*2-4”//= 8(如果我从左到右计算就可以了)

这个操作没问题,但我现在尝试只用 Streams 来做。这意味着我只需要使用过滤、减少、收集等流操作...

我试了 6 个小时,但不知道。不允许在这个方向构建列表和分析元素或其他东西。一个流操作或多个流操作必须直接给我一个最终结果。

有人有什么想法吗?

我最好的尝试是

  Stream<String> numbers = myList.stream().filter(s -> 
  Character.isDigit(s.charAt(0)));
  List<String> operands = myList.stream().filter(s -> 
  !Character.isDigit(s.charAt(0))).collect(Collectors.toList());



   String result = numbers.reduce((a, b) -> {
   int iA = Integer.parseInt(a);
   int iB = Integer.parseInt(b);

   String operation = operands.get(0);
   operands.remove(0);
   return calc(iA,iB,operation);


  }).get();

  System.out.println(result);

更新: 我可能解释得很糟糕。最终结果必须提供流操作。在这个流操作中,我们可以调用辅助方法。

【问题讨论】:

  • 没有流怎么办?我想你也会用同样的方式处理流
  • Stream API 不是灵丹妙药。
  • 不可能减少混合操作流,因为它不会是关联的。
  • @shmosel 对并行流很重要,但我认为这可以仅按顺序运行
  • @Eugene 规范没有区别。它可能会起作用,但这并不意味着它是正确的。

标签: java lambda java-stream reduce


【解决方案1】:

工作解决方案,错别字更正,感谢@Turing85

Java-8 Stream-API 并不是万能的灵丹妙药,而且我看不到任何使用 lambda 表达式的简单解决方案。

我建议你坚持程序的方式去:

String string = "1+5*2-4";

String[] operator = a.split("[0-9]+");
String[] digits = a.split("[+-\\/*]");

int reduced = Integer.parseInt(digits[0]);
for (int i = 1; i < digits.length; i++) {
    if (operator[i].equals("+")) { reduced += Integer.parseInt(digits[i]); } 
    else if (operator[i].equals("/")) { reduced /= Integer.parseInt(digits[i]); } 
    else if (operator[i].equals("*")) { reduced *= Integer.parseInt(digits[i]); } 
    else if (operator[i].equals("-")) { reduced -= Integer.parseInt(digits[i]); }
}

此解决方案仅简化为整数,无需检查输入和字符序列。 reduced 的数量导致8。顺便说一句,不要忘记用\\/ 字符转义两次,因为它在Regex 中有特殊含义。


如果您真的坚持使用基于 Stream-API 的解决方案,它会给出相同的结果,那么您可以这样做:

String a = "1+5*2-4";
System.out.println(a);
String[] operator = a.split("[0-9]+");
String[] digits = a.split("[+-\\/*]");

final int[] index = {0};
int reduced = Stream.of(digits)
                    .mapToInt(Integer::parseInt)
                    .reduce(0, (int t, int u) -> 
{
    int result = Integer.parseInt(digits[0]);
    int i = index[0];
    if (operator[i].equals("+")) { result = t + u; } 
    else if (operator[i].equals("/")) { result = t / u; } 
    else if (operator[i].equals("*")) { result = t * u; } 
    else if (operator[i].equals("-")) { result = t - u; } 
    index[0]++;
    return result;
}); 

我希望你现在可以比较这两个结果,看看哪一个在简洁性和可维护性方面胜出,在我看来,这比炫耀你在 Stream-API 和 lambda 表达式方面的表现更重要。但是,如果您挑战自己以了解有关 Stream-API 的更多信息,我建议您尝试寻找其他用例。 :)


编辑:此外,您应该将操作符数字处理隐藏到方法中:

public static int process(int identity, int t, int u, String[] array, int index) {
    int result = identity;
    if (array[index].equals("+")) { result = t + u; } 
    else if (array[index].equals("/")) { result =  t / u; } 
    else if (array[index].equals("*")) { result =  t * u; } 
    else if (array[index].equals("-")) { result =  t - u; }
    return result;
}

那么我可能会承认 Stream-API 不是一个糟糕的选择。

String a = "1+5*2-4";
System.out.println(a);
String operator[] = a.split("[0-9]+");
String digits[] = a.split("[+-\\/*]");

final int[] index = {0};
int reduced = Stream.of(digits).mapToInt(Integer::parseInt).reduce(0, (int t, int u) -> {
    int result = process(Integer.parseInt(digits[0]), t, u, operator, index[0]);
    index[0]++;
    return result;
}); 

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2012-06-19
  • 1970-01-01
  • 2014-02-06
  • 2017-01-10
  • 1970-01-01
  • 1970-01-01
  • 2021-05-03
  • 1970-01-01
相关资源
最近更新 更多