1. Обзор
Java 8 представила новый Stream
API, который позволяет нам обрабатывать данные декларативным образом.
В этой быстрой статье мы узнаем, как использовать Stream API для разбиения
строки
с разделителями-запятыми на список строк
и как объединить массив строк в
строку
с разделителями-запятыми .
Мы также рассмотрим, как преобразовать массив строк в карту с помощью Stream
API.
Почти все время мы сталкиваемся с ситуациями, когда нам нужно выполнить итерацию некоторых коллекций Java
и отфильтровать коллекцию
на основе некоторой логики фильтрации. При традиционном подходе к такого рода ситуациям мы использовали бы множество циклов и операций if-else, чтобы получить желаемый результат.
Если вы хотите узнать больше о Stream
API, прочтите эту статью .
2. Соединение строк с помощью Stream
API
Давайте воспользуемся Stream
API для создания функции, которая объединит массив String в
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()
преобразует строку
в поток целых чисел
, где каждое целочисленное
значение обозначает значение ASCII
каждой последовательности
символов . Вот почему нам нужно явно привести тип объекта сопоставления в методе mapToObj()
.
4. Массив строк для
сопоставления
с Stream
API
Мы также можем преобразовать массив String
в карту, используя split
и 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 .