2014-02-14 3 views
1

Я пытаюсь удалить дубликат Набор пользовательских объектов из ArrayList. Ниже приведен код, который я написал, который использует toString представление пользовательского EmployeeObj для сравнения. Можете ли вы предложить, какие другие подходы можно предпринять?Удаление дубликатов наборов из списка

package com.collections; 

import java.util.ArrayList; 
import java.util.HashSet; 
import java.util.List; 
import java.util.Set; 

public class DupSetInsideList { 
    public static void main(String[] args) { 
     List<Set<EmployeeObj>> list = new ArrayList<Set<EmployeeObj>>(); 

     Set<EmployeeObj> set1 = new HashSet<EmployeeObj>(); 
     Set<EmployeeObj> set2 = new HashSet<EmployeeObj>(); 
     Set<EmployeeObj> set3 = new HashSet<EmployeeObj>(); 

     list.add(set1); 
     list.add(set2); 
     list.add(set3); 

     EmployeeObj empObj1 = new EmployeeObj(1, "Nikhil"); 
     EmployeeObj empObj2 = new EmployeeObj(2, "Rakesh"); 
     EmployeeObj empObj3 = new EmployeeObj(3, "Kunal"); 

     set1.add(empObj1); 
     set1.add(empObj2); 

     set2.add(empObj1); 
     set2.add(empObj2); 

     set3.add(empObj1); 
     set3.add(empObj2); 
     set3.add(empObj3); 

     System.out.println("List with duplicaes: " + list); 
     //Output: List with duplicaes: [[1=Nikhil, 2=Rakesh], [1=Nikhil, 2=Rakesh], [3=Kunal, 1=Nikhil, 2=Rakesh]] 

     //Remove duplicates 
     List<Set<EmployeeObj>> nonDupList = new ArrayList<Set<EmployeeObj>>(); 
     for(Set<EmployeeObj> obj1:list) { 
      if(!nonDupList.contains(obj1)) { 
       nonDupList.add(obj1); 
      } 
     } 
     System.out.println("List without duplicates: " + nonDupList); 
     //List without duplicates: [[1=Nikhil, 2=Rakesh], [3=Kunal, 1=Nikhil, 2=Rakesh]] 
    } 
} 

class EmployeeObj { 
    private int id; 
    private String name; 

    public int getId() { 
     return id; 
    } 

    public String getName() { 
     return name; 
    } 


    public EmployeeObj(int id, String name) { 
     this.id = id; 
     this.name = name; 
    } 

    @Override 
    public int hashCode() { 
     final int prime = 31; 
     int result = 1; 
     result = prime * result + id; 
     result = prime * result + ((name == null) ? 0 : name.hashCode()); 
     return result; 
    } 

    @Override 
    public boolean equals(Object obj) { 
     if (this == obj) 
      return true; 
     if (obj == null) 
      return false; 
     if (getClass() != obj.getClass()) 
      return false; 
     EmployeeObj other = (EmployeeObj) obj; 
     if (id != other.id) 
      return false; 
     if (name == null) { 
      if (other.name != null) 
       return false; 
     } else if (!name.equals(other.name)) 
      return false; 
     return true; 
    } 

    @Override 
    public String toString() { 
     return id + "=" + name; 
    } 
} 
+0

Почему вы не просто реализовать равных и хэш-код? Таким образом, java сможет увидеть, равно ли по умолчанию 2 объекта. –

+0

проблема в том, что ему нужно переопределить equals и hashCode на объекте HashSet. – WeMakeSoftware

+0

Привет, Курт, Фунтик прав, это своего рода вложенные объекты. Нам нужно сравнить набор элементов, находящихся внутри ArrayList. –

ответ

0

Попробуйте это решение:

private boolean equals(Set elements, Set elements2) { 
    return elements != null && elements.equals(elements2); 
} 

private List<Set> removeDuplicates(List<Set> from) { 
    List<Set> noDuplicates = new ArrayList<Set>(); 

    for (Set possibleDuplicate : from) { 
     boolean alreadyInNoDuplicatesList = false; 
     for (Set elementFromNoDuplicateList : noDuplicates) { 
      if (equals(elementFromNoDuplicateList, possibleDuplicate)) { 
       alreadyInNoDuplicatesList = true; 
       break; 
      } 
     } 
     if (!alreadyInNoDuplicatesList) { 
      noDuplicates.add(possibleDuplicate); 
     } 
    } 

    return noDuplicates; 
} 
+0

ваши равны разбиты как 'equals ([1, 2, 3], [1, 2, 3, 4])' вернет true. Вам нужно будет протестировать в обоих направлениях или проверить один способ и сравнить размер. – aalku

+0

@ user270349 хорошая точка :) Я исправлю это – WeMakeSoftware

+0

@ user270349 исправлено :) – WeMakeSoftware

0

Положите наборы в комплект, и они будут удалены, как по волшебству!

+0

не будет работать, пока вы не переопределите equals() и hashCode() из Set – WeMakeSoftware

+0

Здравствуйте, Kayaman, да, вы правы. Я забыл упомянуть, как мы можем изобрести колесо? Я знаю, что это не требуется, но только для цели обучения. –

+0

@Funtik equals() и hashCode() of Set заданы так, чтобы в этом случае было исключено их переопределение: два набора равны, если они имеют одинаковый размер и содержат одни и те же элементы (независимо от порядка) EDIT: Kayaman: +1 для этого - это был уже правильный ответ! – Marco13

1

Если вы хотите, чтобы поведение списка гарантировало уникальность элементов, используйте LinkedHashSet вместо ArrayList.

Если вы связаны с использованием ArrayList (как в студенческом упражнения), продлить его, перезаписать add и addAll методы, проверяя уникальность первого и последующего вызова super.add соотв. super.addAll, а затем используйте новый класс вместо ArrayList.

+0

Да, LinkedHashSet можно использовать для поддержания порядка вставки. Но здесь List уже построен с использованием элемента HashSet, и из этого нам нужно удалить дубликаты. –

+0

Если вы задаетесь вопросом о сохранении уникальности множеств в вашей внешней структуре, списке, то не имеет значения, что они уже находятся в списке: 'new LinkedHashSet <> (array_of_sets)' будет уничтожать дубликаты точно так же , Если это не то, что вам нужно, тогда, пожалуйста, подумайте о том, чтобы переформулировать свой вопрос: возможно, разместите схему своего алгоритма, а не код относительно длины. –

+0

Привет, Олег, спасибо за быстрый ответ.Я пытаюсь сказать, что - HashSet внутри ArrayList является предопределенным требованием к немедленному изменению - я просто пытаюсь выяснить различные подходы, с помощью которых это можно сделать. –

1

Интерфейс Set определяет метод equals следующим образом:

Сравнивает указанный объект с этим набором для равенства. Возвращает true, если указанный объект также является набором, два набора имеют одинаковый размер, и каждый член указанного набора содержится в этом наборе (или, что эквивалентно, каждый член этого набора содержится в указанном наборе).

Так что для того, чтобы создать список, который не содержит дубликатов (даже если элементы в списке наборы), можно просто написать

//Remove duplicates 
    List<Set<EmployeeObj>> nonDupList = 
     new ArrayList<Set<EmployeeObj>>(
      new LinkedHashSet<Set<EmployeeObj>>(list)); 
+0

Это превосходное решение, действительно крутое. :-) Однако - HashSet внутри ArrayList является предопределенным неотменяемым требованием - я просто пытаюсь выяснить различные подходы, с помощью которых это можно сделать. –

+0

Возможно, вы должны более четко описать это требование. Если Sets - HashSets, то это требование будет выполнено кодом, который я опубликовал. Тот факт, что вы не видите их как HashSets (но только как Sets), вызван тем, что вы не видите их как HashSets в первоначально опубликованном коде! – Marco13

+0

Согласен, хотя ваш ответ добавляет больше информации в мою сумку. Я буду уверен, что следующий вопрос будет более понятным. –

Смежные вопросы