«1. Обзор

В Java 8 появился новый Stream API, который позволяет нам обрабатывать данные декларативным образом.

В этой быстрой статье мы узнаем, как использовать Stream API для разделения строки, разделенной запятыми, на список строк и как объединить массив строк в строку, разделенную запятыми.

Мы также рассмотрим, как преобразовать массив строк в карту с помощью Stream API.

Почти все время мы сталкиваемся с ситуациями, когда нам нужно перебрать некоторые коллекции Java и отфильтровать коллекцию на основе некоторой логики фильтрации. При традиционном подходе к такого рода ситуациям мы использовали бы множество циклов и операций if-else, чтобы получить желаемый результат.

Если вы хотите узнать больше о Stream API, прочтите эту статью.

2. Соединение строк с помощью Stream API

Давайте воспользуемся Stream API для создания функции, которая будет объединять массив String в строку, разделенную запятыми:

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() преобразует строку в поток целых чисел, где каждое значение Integer обозначает значение ASCII для каждой последовательности символов. . Вот почему нам нужно явно привести тип объекта сопоставления в методе mapToObj().

4. Массив строк для сопоставления с помощью Stream API

Мы также можем преобразовать массив строк для сопоставления с помощью разделения и Collectors.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]));
}

Здесь «:» — это разделитель значений ключа для всех элементов массива String.

Пожалуйста, помните, что во избежание ошибок компиляции нам необходимо убедиться, что код компилируется с использованием 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);
}

Наконец, давайте проверим наш массив String для сопоставления функциональности: ~~ ~

@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.