У меня есть объект таблицы с тремя столбцами, которые я использую для фильтрации событий.
Три столбца с гипотетическими значениями:
Component Event SubEvent
A B C
A B D
Я пытаюсь создать поток событий, который отфильтровывает первую строку, но не вторую. Я пробовал это несколько разных способов с неоднозначными результатами.
return events -> save(events.stream().filter(event ->
A != event.getComponent() &&
B != event.getEventType() &&
C != event.getEventSubType())
.collect(Collectors.toList())
Это ведет себя как «или» и отфильтровывает обе строки. т.е. если компонент == A || событие == B || subEvent == C
Я действительно хочу
IF (component == A && event == B && subEvent == C) затем отфильтровать, но сохранить все остальное.
Я изменил свой фильтр на
.filter(event -> C != event.getEventSubType())
Но тогда я рискую пропустить другие события, где subEvent == C, но значения Component и Event не соответствуют A и B.
Оцените любые другие предложения по стратегии по настройке такого сложного фильтра. Спасибо!
@davidxxx, я считаю, что этот вопрос не о равенстве строк.
@M. Прохоров, про которого я не писал ответа. Но проблема связана с фильтром по строковым значениям. Так что их правильное сравнение будет хорошим началом.
зачем писать хрупкий код, чтобы пропустить первую строку? Почему бы не использовать взамен skip(1)?
@davidxxx, мы на самом деле не знаем, правда ли это, определения классов для типа Event не прилагаются. Это может быть enum. Он мог выбрать эти операторы, чтобы код выглядел яснее. Одна версия, которая была удалена при редактировании, определенно выглядела так, как будто там были перечисления.
Что вам здесь не хватает, так это теоремы ДеМоргана: !A && !B == !(A || B) и !A || !B == !(A && B). Вот почему он ведет себя как «или», ваш фильтр !A && !B && !C эквивалентен !(A || B || C).
@ M.Prokhorov, спасибо, вы правы, на самом деле это перечисления, и я просто попытался упростить чтение кода без этих накладных расходов.




Так почему бы не создать фильтр, который точно соответствует сначала строке, а затем инвертирует ее в фильтре потока? Таким образом вы отклоните все события, соответствующие первой строке, например:
Predicate<Event> FIRST_ROW = event->
Object.equals(A , event.getComponent()) &&
Object.equals(B , event.getEventType() &&
Object.equals(C , event.getEventSubType();
save(events.stream()
.filter(FIRST_ROW.negate())
.collect(Collectors.toList())
Попробуйте как
save(events.stream().filter(event ->
!("A".equals(event.getComponent()) &&
"B".equals(event.getEventType()) &&
"C".equals(event.getEventSubType()))
.collect(Collectors.toList())
Или, что то же самое
save(events.stream().filter(event ->
!"A".equals(event.getComponent()) ||
!"B".equals(event.getEventType()) ||
!"C".equals(event.getEventSubType())
.collect(Collectors.toList())
Обратите внимание, что skip(1) позволяет пропустить первый элемент потока.
О вашей проблеме, вашем фактическом фильтре:
filter(event ->
A != event.getComponent() &&
B != event.getEventType() &&
C != event.getEventSubType())
означает, что в потоке хранятся только те элементы, которые соответствуют этим условиям three.
Посмотрите на эти строки:
Component Event SubEvent
A B C
A B D
Условие ложно для первой строки. Таким образом, элемент не сохраняется. Но условие также ложно для второй строки, поскольку последовательность логического И истинна только в том случае, если все условия верны, а два из них не верны:
A != event.getComponent() --> false
B != event.getEventType() --> false
C != event.getEventSubType() --> true
Так что ни одна из этих строк не сохраняется.
Вы должны написать:
filter(event ->
!(A == event.getComponent() &&
B == event.getEventType() &&
C == event.getEventSubType()))
!(A == event.getComponent() && B == event.getEventType() && C == event.getEventSubType()) такой же, как A != event.getComponent() || B != event.getEventType() || C != event.getEventSubType()@Holger Конечно, я не знаю почему, но я считаю, что первый способ более читабельный.
Осторожно: сравните String с equals ().