#java #java-8 #java-stream
#java #java-8 #java-stream
Вопрос:
Я выполняю следующие две операции
- Перебор списка объектов и создание карты
String, Boolean
на основе условия.
Map<String,Boolean> myMap = new HashMap<>();
Iterator<Person> iterator = personList.iterator();
while (iterator.hasNext()) {
Person person = iterator.next();
if (isValidperson(person)) {
if (person.getName() != null) {
myMap.put(person.getName(), true);
} else {
myMap.put(person.getName(), false);
}
}
}
Теперь я проверяю список имен по той карте, которую я создал выше, и, если значение равно true, затем добавляю в окончательный список
List<String> refinedList = new ArrayList<>();
for (String name : nameList) {
if (myMap.get(name) != null amp;amp; myMap.get(name)) {
refinedList.add(name);
}
}
Мне нужно упростить логику с использованием потоков Java. В противном случае все вышеперечисленное работает нормально.
Комментарии:
1. Зачем вам вообще нужна карта? Разве вы не можете просто добавить людей, которые являются действительными людьми и имеют ненулевые имена напрямую
refinedList
?2. @Sweeper Во второй части кода я фактически перебираю другой список имен и проверяю их наличие на карте. ` for (имя строки : список имен) { `
Ответ №1:
В первой операции вы отфильтровываете всех недопустимых пользователей и собираете действительных пользователей на карту, поэтому:
Map<String,Boolean> myMap = personList.stream()
.filter(YourClass::isValidPerson)
.collect(Collectors.toMap(x -> x.getName(), x -> x.getName() != null))
Но на самом деле, карта будет содержать не более одной false
записи, поскольку вы не можете добавить несколько null
s в a HashMap
, поэтому нет особого смысла использовать a HashMap
вообще.
Я предлагаю использовать HashSet
:
Set<String> mySet = personList.stream()
.filter(YourClass::isValidPerson)
.map(Person::getName)
.filter(Objects::nonNull)
.collect(Collectors.toSet())
И тогда вы можете легко проверить contains
с O (1) раз:
List<String> refinedList = nameList.stream().filter(mySet::contains).collect(Collectors.toList());
Комментарии:
1. Или просто
nameList.retainAll(mySet)
, когда исходный список впоследствии не нужен.
Ответ №2:
Вы можете напрямую фильтровать список, проверяя содержит в nameList
и собирать имена в списке
List<String> refinedList =
personList.stream()
.filter(e -> isValidperson(e))
.map(e -> e.getName())
.filter(Objects::nonNull)
.distinct()
.filter(e -> nameList.contains(e))
.collect(Collectors.toList());
И лучше создать набор из nameList
, чтобы ускорить contains()
операцию в O (1)
Set<String> nameSet = new HashSet<String>(nameList);
Примечание: это будет работать, если nameList
не содержит дубликатов.
Комментарии:
1. Вы вроде как изменили логику кода, не так ли? Предполагается, что код получает все элементы
nameList
, которые являются действительным именем пользователя, а не получает все действительные имена пользователей, которые являются элементамиnameList
. Этот код будет давать разные результаты, еслиnameList
, например, содержит дубликаты.
Ответ №3:
Это должно сработать.
Сначала создайте список пользователей.
List<Person> personList = List.of(new Person("Joe"),
new Person(null), new Person("Barb"), new Person("Anne"), new Person("Gary"));
Затем список имен. Обратите внимание, что лучше всего поместить это в набор для
- избегайте дубликатов и
- сделайте процесс поиска более эффективным.
Set<String> nameSet = Set.of("Joe", "Anne", "Ralph");
Теперь это работает следующим образом
- фильтрация по допустимому или недопустимому лицу.
- сопоставление этих людей с именем
- фильтрация по тому, является ли значение null, а затем, если имя находится в наборе имен
- и размещение в списке.
Примечание: В некоторых случаях lambdas
может быть заменен на Method References
в зависимости от типов методов и контекстов вызова.
List<String> names = personList.stream()
.filter(person -> isValidperson(person))
.map(Person::getName)
.filter(name -> name != null amp;amp; nameSet.contains(name))
.collect(Collectors.toList());
System.out.println(names);
С принтами
[Joe, Anne]
Фиктивный метод, поскольку критерии не указаны
public static boolean isValidperson(Person person) {
return true;
}
Простой класс person
class Person {
String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
}