Как удалить дубликаты в коллекций. Без использования Collection.sort Arrays.sort и Comparator. Можно пользоваться Comparable
Дается метод, который принимает лист продуктов. Мне нужно удалить дубликаты продуктов с одинаковым кодом. Попробывал реализовать через stream API,но остановился на настройку equals. Также пробовал с Set, но тоже не вышел результат
public List<Product> distinct(List<Product> products) {
return products.stream().distinct().collect(Collectors.toList());
}
public class Product implements Comparable<Product>{
private int code;
private String title;
public Product(int code, String title) {
this.code = code;
this.title = title;
}
public int getCode() {
return code;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Product product = (Product) o;
return code == product.code && Objects.equals(title, product.title);
}
@Override
public int hashCode() {
return Objects.hash(code, title);
}
public String getTitle() {
return title;
}
@Override
public String toString() {
return "Product{" +
"code=" + code +
", title='" + title + '\'' +
'}';
}
@Override
public int compareTo(Product o) {
return this.title.compareTo(o.getTitle());
}
}
Ответы (2 шт):
все у вас правильно работать должно
public class Main {
public static void main(String[] args) {
List<Product> products = new ArrayList<>();
products.add(new Product(1,"A"));
products.add(new Product(1,"B"));
products.add(new Product(1,"A"));
products.add(new Product(2,"A"));
System.out.println(distinct(products));
}
public static List<Product> distinct(List<Product> products) {
return products.stream().distinct().collect(Collectors.toList());
}
}
вывод
[Product{code=1, title='A'}, Product{code=1, title='B'}, Product{code=2, title='A'}]
сравнение идет по методу Equals если нужно сравнить только по коду поменяйте на
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Product product = (Product) o;
return code == product.code;
}
@Override
public int hashCode() {
return Objects.hash(code);
}
вывод после
[Product{code=1, title='A'}, Product{code=2, title='A'}]
Не совсем понятно, каким образом здесь можно применить Comparable, предназначенный для упорядочивания последовательности по возрастанию/убыванию, который к тому же в данной реализации сравнивает названия продуктов, а не коды, что позволяет отсортировать список/массив продуктов по названию в алфавитном порядке.
Также существующие реализации методов hashCode / equals, использующие оба поля класса Product не позволят обнаружить дубликаты только по одному полю code.
Для поиска дубликатов по одному полю требуется сгруппировать объекты в списке по этому полю, и тогда в зависимости от определения что считать "дубликатом" вернуть некий результат.
Например, для входных данных:
List<Product> products = Arrays.asList(
new Product(1,"A"), new Product(1,"B"), new Product(1,"A"), new Product(2,"A")
);
после группировки по коду можно оставить:
- только
Product(2,"A")- у него уникальный код, - или же набор продуктов
Product(1,"A"), Product(2,"A")- продукты с повторным кодом 1 были отброшены.
Здесь удобно применить коллекторы Collectors.groupingBy, Collectors.toMap, причём их можно параметризовать по геттеру/полю, по которому надо отфильтровать дубликаты Product::getCode или Product::getTitle
public static <T> List<Product> distinct(List<Product> products, Function<Product, T> getter) {
return new ArrayList<>(
products.stream()
.collect(Collectors.toMap(
getter, p -> p, (p1, p2) -> p1, LinkedHashMap::new
))
.values()
);
}
public static <T> List<Product> unique(List<Product> products, Function<Product, T> getter) {
return products
.stream()
.collect(Collectors.groupingBy(getter))
.values()
.stream()
.filter(list -> list.size() == 1)
.map(list -> list.get(0))
.collect(Collectors.toList());
}
Тесты:
List<Product> products = Arrays.asList(
new Product(1,"A"), new Product(1,"B"),
new Product(1,"A"), new Product(2,"A")
);
System.out.println("Distinct");
System.out.println(distinct(products, Product::getCode));
System.out.println(distinct(products, Product::getTitle));
System.out.println("Unique");
System.out.println(unique(products, Product::getCode));
System.out.println(unique(products, Product::getTitle));
Результаты:
Distinct
[Product{code=1, title='A'}, Product{code=2, title='A'}]
[Product{code=1, title='A'}, Product{code=1, title='B'}]
Unique
[Product{code=2, title='A'}]
[Product{code=1, title='B'}]