Объединение в операции с использованием потоков Java

#java #java-8 #java-stream

#java #java-8 #java-stream

Вопрос:

Я выполняю следующие две операции

  1. Перебор списка объектов и создание карты 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"));
  

Затем список имен. Обратите внимание, что лучше всего поместить это в набор для

  1. избегайте дубликатов и
  2. сделайте процесс поиска более эффективным.
 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;
    }
}