Фильтрация потоков Java 8 с приоритетом - PullRequest
0 голосов
/ 17 октября 2018

У меня есть код, который выглядит следующим образом:

for (SomeObject object : objects) {
    if (object.getSomething() == Something.SomethingHighPriority) {
        return object;
    }
}

for (SomeObject object : objects) {
    if (object.getSomething() == Something.SomethingLowPriority) {
        return object;
    }
}

Он используется для получения первого элемента в коллекции по некоторому условию.Также важен приоритет.Во-первых, мне нужно найти один элемент, а просто, если он не существует, найти второй.

Я хочу переписать его с помощью Stream API, но я знаю, что потоки используются только один раз.Сейчас я переписал его таким образом, но он кажется более уродливым, чем раньше.

Optional<SomeObject> object = 
    objects.stream()
           .filter(object -> object.getSomething() == Something.SomethingHighPriority)
           .findFirst();

if (object.isPresent()) {
    return object.get();
}

object = objects.stream()
                .filter(object -> object.getSomething() == Something.SomethingLowPriority)
                .findFirst();

// No other use cases
return object.orElse(null);

Можно ли сделать его менее шаблонным?

Ответы [ 3 ]

0 голосов
/ 17 октября 2018

Я думаю, что ваш код в порядке, итерация коллекции дважды - не плохой подход.

Но если вы хотите сделать это только за один проход, вы можете собрать до Map:

Map<Something.Priority, Something> map = objects.stream()
    .filter(o -> o.getSomething() == Something.SomethingHighPriority
              || o.getSomething() == Something.SomethingLowPriority)
    .collect(Collectors.toMap(
                SomeObject::getSomething,
                Function.identity(),
                (oldObject, newObject) -> oldObject));

SomeObject highPriority = map.get(Something.SomethingHighPriority);

return highPriority == null ? map.get(Something.SomethingLowPriority) : highPriority;
0 голосов
/ 26 июля 2019

Не уверен, что SomethingHighPriority значит для вас, но вы можете попробовать с Comparator.Сначала создайте два предиката для высокого и низкого уровня.Добавьте их в фильтр с помощью оператора или, так как вам нужно как сравнить, так и получить максимум.

    Predicate<SomeObject> somethingHighPriority= e -> e.getSomething() == Something.SomethingHighPriority;
    Predicate<SomeObject> somethingLowPriority= e -> e.getSomething() == Something.SomethingLowPriority;
    Optional<SomeObject> first = objects.stream()
            .filter(somethingHighPriority.or(somethingLowPriority)) 
            .max(Comparator.comparing(objects::getSomething()));

    if (first.isPresent()) {
        return first.get();
    }
    return null;

Максимум будет обрабатывать приоритет

0 голосов
/ 17 октября 2018

Вы можете связать два конвейера:

return objects.stream()
              .filter(object -> object.getSomething() == Something.SomethingHighPriority)
              .findFirst()
              .orElseGet(() -> objects.stream()
                                      .filter(object -> object.getSomething() == Something.SomethingLowPriority)
                                      .findFirst()
                                      .orElse(null));

Альтернативой может быть сортировка Stream по object.getSomething() в порядке убывания, а затем возврат первого элемента (если он имеет один из двухтребуемые значения), но для этого потребуется O(NlogN), что менее эффективно.

...