У меня есть требование получить подсписок из заданного суперсписка, как описано ниже.
Скажем, у меня есть супер-список объектов "Человек", как показано ниже:
List<Person> personsList = new ArrayList<>();
personsList.add(new Person("John", 28));
personsList.add(new Person("Paul", 29));
personsList.add(new Person("Adam", 30));
personsList.add(new Person("Peter", 31));
personsList.add(new Person("Pat", 32));
Пусть класс Person определяется следующим образом:
class Person {
public String name;
public int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return name + ": " + age;
}
}
Учитывая такой подсписок:
String [] names = {"John", "Paul", "Adam"};
List<String> namesList = Arrays.asList(names);
Я хотел бы получить объекты Person с именем John, Paul и Adam.
Я новичок в потоках Java, и это то, что я пытался до сих пор, чтобы удовлетворить мои требования.
List<Person> finalList = personsList.stream().filter(p -> namesList.contains(p.name))
.collect(Collectors.toCollection(() -> new ArrayList<Person>()));
Я получил желаемый результат, но хотел бы знать, есть ли какой-либо другой эффективный метод для достижения этого (я в основном смотрю на namesList.contains (p.name) как на немного неэффективный).
Пожалуйста, дайте мне знать, если есть лучший способ сделать это.




Определение nameList как Set будет более эффективным, хотя, если список содержит только 3 имени, разница действительно будет не заметна.
Так что-то вроде этого:
Set<String> namesList = new HashSet<> (Arrays.asList("John", "Paul", "Adam"));
List<Person> finalList = personsList.stream()
.filter(p -> namesList.contains(p.name))
.collect(Collectors.toList());
Примечание: я также изменил коллектор на toList, так как он, по-видимому, вам нужен.
Предположим, что нет смысла иметь повторяющиеся имена в массиве, лучший способ - найти имя в Set<T> имен. Этого легко добиться. Преобразуйте массив в список и включите его в конструктор HashSet<T>, как только он примет любую коллекцию.
String [] names = {"John", "Paul", "Adam"};
Set<String> set = new HashSet<>(Arrays.asList(names));
Теперь используйте Stream-API так же, как вы пробовали. Используйте только статический метод Collectors.toList().
List<Person> list= personsList.stream()
.filter(i -> set.contains(i.getName()))
.collect(Collectors.toList());
Результат будет содержать только объекты лиц John, Paul и Adam.
Спасибо, @Nikolas. Итак, моя основная идея использования "содержит" все еще хороша, хотя тогда я мог бы использовать Collectors.toList (). Кроме того, я считаю, что это опечатка в вашем ответе, когда говорится, что результат будет содержать только объекты «Питер» и «Пэт»?
Я редактировал это. Это, конечно, было моей бедой. :) Stream :: filter возвращает Stream с элементами, соответствующими заданному предикату.
Спасибо @assylias. Итак, моя основная идея использования "содержит" все еще хороша, хотя тогда я мог бы использовать Collectors.toList ().