1. 概述

Java 8 引入了一个新的流(Stream) API,它允许我们以声明式的方式处理数据。

在这篇简短的文章中,我们将学习如何使用流(Stream) API 将逗号分隔的字符串分解成字符串列表,以及如何将字符串数组合并成一个逗号分隔的字符串。我们还将探讨如何使用流(Stream) API 将字符串数组转换为映射。

在大多数情况下,我们都需要遍历Java集合并根据某些过滤逻辑对集合进行过滤。传统上,对于这种场景,我们会使用大量循环和if-else语句来获取期望的结果。

如果你想了解更多关于流(Stream) API的内容,请参阅这篇文章

2. 使用流(Stream) API 合并字符串

让我们使用流(Stream) API 来创建一个函数,将字符串数组合并成一个逗号分隔的字符串:

public static String join(String[] arrayOfString){
    return Arrays.asList(arrayOfString)
      .stream()
      //.map(...)
      .collect(Collectors.joining(","));
}

这里需要注意:

  • stream() 函数将任何集合转换为数据流。
  • map() 函数用于处理数据。
  • 还有一个名为filter()的函数,我们可以在此处包含过滤条件。

有些情况下,我们可能希望在字符串前后添加固定的前缀和后缀。使用流(Stream) API,我们可以这样做:

public static String joinWithPrefixPostfix(String[] arrayOfString){
    return Arrays.asList(arrayOfString)
      .stream()
      //.map(...)
      .collect(Collectors.joining(",","[","]"));
}

Collectors.joining()方法所示,我们声明了前缀为['和后缀为'];因此生成的字符串将以[……]格式创建。

3. 使用流(Stream) API 分割字符串

现在,让我们创建一个函数,使用流(Stream) API 将逗号分隔的字符串分解成字符串列表:

public static List<String> split(String str){
    return Stream.of(str.split(","))
      .map (elem -> new String(elem))
      .collect(Collectors.toList());
}

同样,我们也可以直接使用流(Stream) API 将字符串转换为字符列表:

public static List<Character> splitToListOfChar(String str) {
    return str.chars()
      .mapToObj(item -> (char) item)
      .collect(Collectors.toList());
}

这里的一个有趣事实是,chars()方法将字符串转换为整数流,其中每个整数值表示每个字符序列的ASCII值。这就是为什么我们在mapToObj()方法中需要显式地将映射对象类型转换。

4. 使用流(Stream) API 将字符串数组转换为映射

我们还可以使用splitCollectors.toMap将字符串数组转换为映射,前提是数组中的每个元素都包含由分隔符连接的键值对:

public static Map<String, String> arrayToMap(String[] arrayOfString) {
    return Arrays.asList(arrayOfString)
      .stream()
      .map(str -> str.split(":"))
      .collect(toMap(str -> str[0], str -> str[1]));
}

这里,":"是字符串数组中所有元素的键值分隔符。

请记住,为了避免编译错误,我们需要确保代码是使用Java 1.8编译的。为此,我们需要在pom.xml中添加以下插件:

<build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.3</version>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>
      </plugin>
    </plugins>        
</build>

5. 测试

既然我们已经创建了函数,让我们编写测试用例来验证结果。

首先,让我们测试我们的简单合并方法:

@Test
public void givenArray_transformedToStream_convertToString() {
    String[] programmingLanguages = {"java", "python", "nodejs", "ruby"};
    String expectation = "java,python,nodejs,ruby";

    String result  = JoinerSplitter.join(programmingLanguages);
    assertEquals(result, expectation);
}

接下来,让我们创建另一个测试用例来测试简单的分割功能:

@Test
public void givenString_transformedToStream_convertToList() {
    String programmingLanguages = "java,python,nodejs,ruby";

    List<String> expectation = new ArrayList<>();
    expectation.add("java");
    expectation.add("python");
    expectation.add("nodejs");
    expectation.add("ruby");

    List<String> result  = JoinerSplitter.split(programmingLanguages);

    assertEquals(result, expectation);
}

最后,让我们测试我们的字符串数组到映射的功能:

@Test
public void givenStringArray_transformedToStream_convertToMap() {

    String[] programming_languages = new String[] {"language:java","os:linux","editor:emacs"};
    
    Map<String,String> expectation=new HashMap<>();
    expectation.put("language", "java");
    expectation.put("os", "linux");
    expectation.put("editor", "emacs");
    
    Map<String, String> result = JoinerSplitter.arrayToMap(programming_languages);
    assertEquals(result, expectation);
    
}

同样,我们需要为其他测试用例创建相应的代码。

6. 总结

流(Stream) API 提供了高级的数据处理技术。这种新的编程方式在多线程环境中对堆内存管理非常高效。

一如既往,完整的源代码可在GitHub上找到。