Есть ли способ добиться этого с помощью Java Streams?
List<String> list = new ArrayList<>();
list.add("x=aa,y=bb,y=cc");
list.add("y=dd,z=ee,w=ff");
list.add("w=gg,w=hh,w=ii");
и я хочу отфильтровать выше ArrayList, чтобы он содержал только строковые значения типа «y». Как ниже
list=["bb","cc","dd"]
Я могу добиться этого, используя несколько строк кода, используя String.split(",") и вставляя подходящую подстроку в новый ArrayList. Но есть ли чистый способ добиться этого с помощью Java Streams?
Ты спрашивал:
is there a clean way to achieve this using Java Streams?
Да. Действительно, вы можете обрабатывать свои входные данные, отфильтровывать ненужные части и создавать готовый список, используя потоки.
Сначала определите некоторые примеры данных, входы список.
Создайте поток из этого списка. Этот поток имеет 3 элемента, учитывая данные нашего примера.
Вызовите Stream#flatMap
, чтобы вернуть новый поток, элементы которого состоят из частей элементов исходного потока. Новый поток состоит из 9 элементов, полученных путем разбиения каждого из 3 исходных элементов на 3 части (3 * 3 = 9).
Фильтр — новый более длинный поток для элементов, текст которых начинается с нашего целевого префикса y=
.
Преобразуйте каждый из строковых элементов, которые прошли тест предикат нашего фильтра. Используйте простые манипуляции со строками для заменять "y=" с пустой строкой. Таким образом, значение, такое как y=bb
, становится bb
.
Соберите преобразованные строки, объединив их в новый объект List
.
List < String > inputs =
List.of(
"x=aa,y=bb,y=cc" ,
"y=dd,z=ee,w=ff" ,
"w=gg,w=hh,w=ii"
);
List < String > results =
inputs
.stream() // Generate stream whose elements are each of the list’s elements.
.flatMap( input -> Arrays.stream( input.split( "," ) ) ) // Break each element into parts, feeding each part into a new longer stream.
.filter( pairing -> pairing.startsWith( "y = " ) ) // Filter out any strings not beginning with `y=`.
.map( pairing -> pairing.replace( "y = " , "" ) ) // A value such as `y=bb` becomes `bb`.
.toList(); // Collect transformed strings into a new list.
Когда бег.
results.toString() = [bb, cc, dd]
Чтобы отсортировать результаты, добавьте вызов .sorted()
перед toList()
.
Вот один из способов.
List<String> list = new ArrayList<>();
list.add("x=aa,y=bb,y=cc");
list.add("y=dd,z=ee,w=ff");
list.add("w=gg,w=hh,w=ii");
List<String> result = getListOf(list,"y");
System.out.println(result);
отпечатки
[bb, cc, dd]
","
" = "
, который возвращает массивы, такие как arr = [x,aa]
arr[0]
и верните arr[1]
, если он совпадает.public static List<String> getListOf(List<String> items, String key) {
return items.stream()
.flatMap(str -> Arrays.stream(str.split(",")))
.map(str -> str.split(" = "))
.filter(s -> s[0].equals(key))
.map(s -> s[1])
.toList();
}
Вы можете избежать flatMapping, используя mapMulti
(Java 16). Примечание: украл идею startsWith
из ответа Бэзил Бурк.
public static List<String> getListOf(List<String> items, String key) {
final String kk = key+" = ";
return items.stream().<String>mapMulti((str,putOnStream)-> {
for (String s : str.split(",")) {
if (s.startsWith(kk)) {
putOnStream.accept(s.substring(kk.length()));
}
}})
.toList();
}