Добавление строки при поиске дубликата с помощью stream

#java #list #java-8 #java-stream

#java #Список #java-8 #java-stream

Вопрос:

У меня действительно есть вариант использования, когда мне нужно добавить строку (name) с версией (name_version), которая у меня будет на уровне модели. Но это должно быть сделано только для имени, которое дублируется в списке.

Student.java

 private class Student{
        private String name;
        private String value;
}
  

Test.java

 public class NewTes {
    public static void main(String[] args){
            
            Student s1 = new Student("xyz","a1");
            Student s2 = new Student("abc","a2");
            Student s3 = new Student("xyz","a3");
            List<String> l2 = new ArrayList<>();
            List<Student> l1 = new ArrayList<Student>();
            l1.add(s1);
            l1.add(s2);
            l1.add(s3);
            
            //Get only names from the list
            l1.stream().forEach(e -> l2.add(e.getName()));
            
            // Output is
            //{"xyz","abc","xyz"}
    
            //Finding only the duplicate ones
            Set<String> result = l2.stream().filter(i -> Collections.frequency(l2, i) > 1).collect(Collectors.toSet());
            
            //Output is
            //{"xyz"}
            
            //Not sure how to proceed from here
            l1.stream().map(e -> e.getName()).flatMap(x -> result.contains(x) ? Stream.of(x   ))
            
            //expected output
            //{"xyz_a1", "abc" , "xyz_a3"}
        }
}
  

Ответ №1:

используя ваши предыдущие списки из вашего вопроса.. ниже должен быть приведен желаемый результат —

 l1.stream()
  .map(e -> result.contains(e.getName())? String.join("_",e.getName(),e.getValue()) : e.getName())
  .collect(Collectors.toList());
  

Комментарии:

1. Да, это работает. Пропустил, что это можно сделать в самой карте вместо flatMap. Спасибо

Ответ №2:

Хорошей идеей будет переопределить equals и hashCode в вашем классе. Если бы вы сделали это для сравнения по name полю, вам не понадобилось бы Set собирать дубликаты. Вы могли бы сделать это следующим образом:

 List<String> list = l1.stream()
        .map(e -> Collections.frequency(l1, e) > 1 ?
                String.join("_", e.getName(), e.getValue()) :
                e.getName())
        .collect(Collectors.toList());

list.forEach(System.out::println);
  

С принтами

 xyz_a1
abc
xyz_a3