Streams:Streams中的map如何工作

时间:2016-12-02 11:49:50

标签: java java-8 java-stream

为了更好地理解Streams中的map函数,我尝试了这样的事情:

String inputString="1+3+5";
Stream.of(inputString.split("\\+")).map(
    eachStringLiteral -> {
        output += mapOfStringAndNumber.get(eachStringLiteral) + literal;
    }
);

inputString 的位置是:

String inputString = "1+3+5";

然而,编译器抱怨并且我不知道为什么:

  

类型中的方法图(Function)   Stream不适用于参数((   eachStringLiteral) - > {})

我还需要一些帮助才能理解

中的语法

Function<? super String,? extends R>

更新

这是完整的代码,说明了我想要实现的目标:

HashMap<String,Double> mapOfStringAndNumber=new HashMap<String,Double>();

        mapOfStringAndNumber.put("1",270.5);
        mapOfStringAndNumber.put("2",377.5);
        mapOfStringAndNumber.put("3",377.5);
        String inputString="1+3+5";
        String literal="+";
       String output;
      java.util.stream.Stream.of(inputString.split("+")).map(eachStringLiteral->
      output+=mapOfStringAndNumber.get(eachStringLiteral)+literal

4 个答案:

答案 0 :(得分:2)

假设您为地图Double中的每个输入String提供mapOfStringAndNumber值,您可以使用Pattern#splitAsStream(CharSequence input)直接将输入String拆分为Stream并使用Collectors.joining(CharSequence delimiter)构建output +作为分隔符,因此您的最终代码可以是:

Map<String,Double> mapOfStringAndNumber = new HashMap<>();
mapOfStringAndNumber.put("1",270.5);
mapOfStringAndNumber.put("3",377.5);
mapOfStringAndNumber.put("5",377.5);
String inputString = "1+3+5";
String output = Pattern.compile("\\+")
    .splitAsStream(inputString)
    .map(mapOfStringAndNumber::get)
    .map(d -> Double.toString(d))
    .collect(Collectors.joining("+"));

System.out.println(output);

<强>输出:

270.5+377.5+377.5

答案 1 :(得分:2)

根据定义,

map获取输入流并将Function应用于此流的每个元素,从这些已修改的元素中创建新流。

因此,输入流中的项目数与输出流中的项目数相同。

您提到的错误发生了,因为您的映射函数没有返回任何内容:output+=mapOfStringAndNumber.get(eachStringLiteral)+literal仅修改output变量并且不返回任何内容。

根据我在此处看到的内容,您希望执行mapreduce操作:

  • map操作会将输入流的每个元素更改为mapOfStringAndNumber的值并向其添加literal
  • 在您的情况下,
  • reduce操作正在汇总您的信息流的所有元素

要使用Java 8功能实现此目的,您需要首先map流的元素,然后总结它们。你可以这样做:

String sum = Stream.of(inputString.split("\\+"))
       .map(stringLiteral->
          mapOfStringAndNumber.get(stringLiteral).toString())
       //join all the strings in the stream with a provided delimiter
       .collect(Collectors.joining(literal));

答案 2 :(得分:2)

我对您的代码提出了一些建议:

  1. 如果您使用{} - 阻止,并且想要创建Function(不是RunnableConsumer或类似代码),则必须 {{ 1}}
  2. 除非你有一个非常特殊的情况,否则使用Integer.parseInt(String)而不是整数字符串映射
  3. 您不得在Stream中修改return。这可能导致一致的问题。
  4. 你真的需要output吗?
  5. 我的用例示例代码如下所示:

    literal

答案 3 :(得分:1)

output+=mapOfStringAndNumber.get(eachStringLiteral)+literal;是一个表达式。具有由单个表达式组成的主体的Lambda表达式不应将它们放在花括号中:

Stream.of(inputString.split("+")).map(eachStringLiteral -> 
  output+=mapOfStringAndNumber.get(eachStringLiteral)+literal;
);

请参阅有关lambda bodies的Java语言规范部分:

  

lambda主体是单个表达式或块(第14.2节)......

LambdaBody:
     
Expression
Block
  

或者,您可以在return变量之前添加output子句,以使其成为声明。