Недавно мы опубликовали нашу статью о потрясающей поддержке оконных функций в jOOλ 0.9.9 , которая, я считаю, является одним из лучших дополнений к библиотеке, которые мы когда-либо делали.
Сегодня мы рассмотрим удивительное применение оконных функций в сценарии использования, вдохновленном этим вопросом переполнения стека Шон Нгуен:
Как получить строки до и после сопоставления из потока Java 8, как grep?
У меня есть текстовые файлы, в которых много строк. Если я хочу найти строки до и после сопоставления в grep, я сделаю так:
1grep
-A 10 -B 10
"ABC"
myfile.txt
Как я могу реализовать эквивалент в Java 8, используя потоки?
Итак, вопрос:
Как я могу реализовать эквивалент в Java 8, используя потоки?
Что ж, оболочка Unix и ее различные «pipable» команды — это единственное, что еще более удивительно (и таинственно), чем оконные функции. Возможность найти определенную строку в файле, а затем отобразить «окно» из нескольких строк, весьма полезна.
Однако с jOOλ 0.9.9 мы можем сделать это очень легко и в Java 8 . Посмотрите на этот маленький фрагмент:
01
02
03
04
05
06
07
08
09
10
11
|
Seq.seq(Files.readAllLines(Paths.get( new File( "/path/to/Example.java" ).toURI()))) .window() .filter(w -> w.value().contains( "ABC" )) .forEach(w -> { System.out.println(); System.out.println( "-1:" + w.lag().orElse( "" )); System.out.println( " 0:" + w.value()); System.out.println( "+1:" + w.lead().orElse( "" )); // ABC: Just checking }); |
Эта программа выведет:
1
2
3
4
5
6
7
|
- 1 : .window() 0 : .filter(w -> w.value().contains( "ABC" )) + 1 : .forEach(w -> { - 1 : System.out.println( "+1:" + w.lead().orElse( "" )); 0 : // ABC: Just checking + 1 : }); |
Итак, я запустил программу сам и нашел все строки, которые соответствуют «ABC», плюс предыдущие строки («lagging» / lag()
) и следующие строки ( lead()
/ lead()
). Эти функции lead()
и lag()
работают так же, как их SQL-эквиваленты .
Но в отличие от SQL, составление функций в Java (или других языках общего назначения) немного проще, так как здесь меньше синтаксического беспорядка. Мы можем легко выполнить агрегацию по рамке окна, чтобы собрать общее количество строк, «отстающих» и «ведущих» совпадение. Рассмотрим следующую альтернативу:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
int lower = - 5 ; int upper = 5 ; Seq.seq(Files.readAllLines(Paths.get( new File( "/path/to/Example.java" ).toURI()))) .window(lower, upper) .filter(w -> w.value().contains( "ABC" )) .map(w -> w.window() .zipWithIndex() .map(t -> tuple(t.v1, t.v2 + lower)) .map(t -> (t.v2 > 0 ? "+" : t.v2 == 0 ? " " : "" ) + t.v2 + ":" + t.v1) .toString( "\n" )) |
И результат, который мы получаем:
01
02
03
04
05
06
07
08
09
10
11
|
- 5 : int upper = 5 ; - 4 : - 3 :Seq.seq(Files.readAllLines(Paths.get( - 2 : new File( "/path/to/Example.java" ).toURI()))) - 1 : .window(lower, upper) 0 : .filter(w -> w.value().contains( "ABC" )) + 1 : .map(w -> w.window() + 2 : .zipWithIndex() + 3 : .map(t -> tuple(t.v1, t.v2 + lower)) + 4 : .map(t -> (t.v2 > 0 + 5 : ? "+" |
Может ли это быть более кратким? Я так не думаю. Большая часть логики выше просто генерировала индекс рядом со строкой.
Вывод
Оконные функции очень мощные. Недавнее обсуждение reddit о нашей предыдущей статье о поддержке оконных функций jOOλ показало, что другие языки также поддерживают примитивы для создания аналогичной функциональности. Но обычно эти строительные блоки не так лаконичны, как те, что представлены в jOOλ, вдохновленные SQL.
Благодаря jOOλ, имитирующему оконные функции SQL, при составлении мощных операций в потоках данных в памяти практически не возникает когнитивных трений.
Узнайте больше об оконных функциях в этих статьях здесь:
- Вероятно, самая крутая особенность SQL: оконные функции
- Используйте этот аккуратный трюк с функцией окна для расчета разницы во времени во временном ряду
- Как найти самую длинную последовательность событий в SQL
- Не упустите возможности SQL Power с FIRST_VALUE (), LAST_VALUE (), LEAD () и LAG ()
- Разница между ROW_NUMBER (), RANK () и DENSE_RANK ()
Ссылка: | Как сопоставлять шаблоны и отображать смежные строки в Java от нашего партнера по JCG Лукаса Эдера из блога JAVA, SQL и AND JOOQ . |