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