在Java中从列表中删除重复的对象

在Java中从列表中删除重复的对象,java,arraylist,data-structures,linked-list,core,Java,Arraylist,Data Structures,Linked List,Core,我知道以前很多时候都会问这种问题。但我的问题有点不同,我找不到任何类似的情况,所以在这里发布这个问题 问题: 我需要从ArrayList中删除重复的对象。我的arrayList的结构如下所示 dataList.add(new ObjectClass("a","b")); dataList.add(new ObjectClass("c","n")); dataList.add(new ObjectClass("b","a")); // should be counted as duplicate

我知道以前很多时候都会问这种问题。但我的问题有点不同,我找不到任何类似的情况,所以在这里发布这个问题

问题: 我需要从ArrayList中删除重复的对象。我的arrayList的结构如下所示

dataList.add(new ObjectClass("a","b"));
dataList.add(new ObjectClass("c","n"));
dataList.add(new ObjectClass("b","a")); // should be counted as duplicate
dataList.add(new ObjectClass("z","x"));
我需要从上面的列表中删除对象,例如,它将“a,b”和“b,a”的组合视为重复项,并删除任何重复项

我的解决方案: 步骤1)重写DataClass中的equals方法

class DataClass {
      String source;
      String destination;

      DataClass(String src, String dest) {
        this.source = src;
        this.destination = dest;
      }

      // getter setter for source and destination variables

    @Override
    public boolean equals(Object obj) {
        System.out.println("inside equals");
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        ObjectClass other = (ObjectClass) obj;
        if(i.equals(other.getJ())
            && j.equals(other.getI())) {
            return true;
        } else return false;
    }
步骤2)删除重复项的方法

public List<DataClass> removeDuplicates(List<DataClass> dataList) {
            List<DataClass> resultList = new ArrayList<DataClass>();

            // Convert array list to Linked list
            LinkedList<DataClass> linkedList = new LinkedList<DataClass>();
            for(DataClass obj: dataList) {
                linkedList.add(obj);
            }

            // Iterate through linked list and remove if values are duplicates
            for(int i = 0; i<linkedList.size();i++) {
              for(int j = i+1;j<linkedList.size();j++) {
                if(linkedList.get(j).equals(linkedList.get(i))) {
                    linkedList.remove();
                }
              }
            }
            resultList.addAll(linkedList);
            return resultList;
        }
2) 在修复了equals方法之后,我尝试了下面的RemovedUpplicate方法实现,正如Janos所提到的,它工作正常

    for(ObjectClass obj: dataList) {
        if(!resultList.contains(obj))
            resultList.add(obj);
    }
非常感谢

示例:

DataClass dc = new DataClass("a","b");
List<DataClass> resultList = new ArrayList<DataClass>();
resultList .add(dc);

for (int i=0; i < resultList.size(); i++) {
 if(resultList.get(i).source.equals(dc.source) && resultList.get(i).destination.equals(dc.destination) || resultList.get(i).source.equals(dc.destination) && resultList.get(i).destination.equals(dc.source)) {
    resultList.remove(i);
 }
}
DataClass dc=新的数据类(“a”、“b”);
List resultList=new ArrayList();
结果列表添加(dc);
对于(int i=0;i
示例:

DataClass dc = new DataClass("a","b");
List<DataClass> resultList = new ArrayList<DataClass>();
resultList .add(dc);

for (int i=0; i < resultList.size(); i++) {
 if(resultList.get(i).source.equals(dc.source) && resultList.get(i).destination.equals(dc.destination) || resultList.get(i).source.equals(dc.destination) && resultList.get(i).destination.equals(dc.source)) {
    resultList.remove(i);
 }
}
DataClass dc=新的数据类(“a”、“b”);
List resultList=new ArrayList();
结果列表添加(dc);
对于(int i=0;i
equals
hashCode
使用
HashSet
,这样它就不会区分顺序:

class DataClass {
  String source;
  String destination;
  private final Set<String> content = new HashSet< String >();

  DataClass(String src, String dest) {
    this.source = src;
    this.destination = dest;
    content.add(src);
    content.add(dest);
  }

  // getter setter for source and destination variables

@Override
public boolean equals(Object obj) {
    System.out.println("inside equals");
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (!DataClass.class.equals(obj.getClass()))
        return false;
    DataClass other = (DataClass) obj;
    return content.equals(other.content);
}

public int hashCode() {
    return content.hashCode();
}
为什么我们使用
LinkedHashSet
而不是
HashSet
LinkedHashSet
保留排序,而
HashSet
不保留排序。引用自
LinkedHashSet
javadoc:

此实现与HashSet的不同之处在于它维护 贯穿其所有条目的双链接列表。此链接 列表定义了迭代顺序,即 元素被插入到集合中(插入顺序)


使用
HashSet
表示
equals
hashCode
,使其不区分顺序:

class DataClass {
  String source;
  String destination;
  private final Set<String> content = new HashSet< String >();

  DataClass(String src, String dest) {
    this.source = src;
    this.destination = dest;
    content.add(src);
    content.add(dest);
  }

  // getter setter for source and destination variables

@Override
public boolean equals(Object obj) {
    System.out.println("inside equals");
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (!DataClass.class.equals(obj.getClass()))
        return false;
    DataClass other = (DataClass) obj;
    return content.equals(other.content);
}

public int hashCode() {
    return content.hashCode();
}
为什么我们使用
LinkedHashSet
而不是
HashSet
LinkedHashSet
保留排序,而
HashSet
不保留排序。引用自
LinkedHashSet
javadoc:

此实现与HashSet的不同之处在于它维护 贯穿其所有条目的双链接列表。此链接 列表定义了迭代顺序,即 元素被插入到集合中(插入顺序)


这里有几个问题:

equals
方法将另一个对象强制转换为
ObjectClass
。 它应该强制转换到定义此方法的同一类:
DataClass

equals
方法比较
i
j
变量, 但是它们没有在类中的任何地方定义。 有
目的地

this.i
other.j
相同且
this.j
other.i
相同时,
equals
方法将返回true,否则返回false。换句话说,
(a,b)
将等于
(b,a)
。但它并不等于它自己。这很奇怪,可能不是你想要的


removeDuplicates
方法过于复杂。 例如,不需要将数组列表转换为链表。 下面是一个简单得多的算法:

  • 对于源列表中的每个值
    • 如果结果列表中不存在该值,请将其添加到结果列表中
就这样

List<DataClass> result = new ArrayList<>();

for (DataClass item : dataList) {
    if (!result.contains(item)) {
        result.add(item);
    }
}
return result;
List result=new ArrayList();
用于(数据类项:数据列表){
如果(!result.contains(项)){
结果.添加(项目);
}
}
返回结果;
这假设
equals
方法的实现是固定的。 否则,
result.contains
步骤将无法正常工作

还要注意,
result.contains
执行线性搜索: 它检查每个项目,直到找到匹配项。
您可以通过使用集合来提高性能。

这里有几个问题:

equals
方法将另一个对象强制转换为
ObjectClass
。 它应该强制转换到定义此方法的同一类:
DataClass

equals
方法比较
i
j
变量, 但是它们没有在类中的任何地方定义。 有
目的地

this.i
other.j
相同且
this.j
other.i
相同时,
equals
方法将返回true,否则返回false。换句话说,
(a,b)
将等于
(b,a)
。但它并不等于它自己。这很奇怪,可能不是你想要的


removeDuplicates
方法过于复杂。 例如,不需要将数组列表转换为链表。 下面是一个简单得多的算法:

  • 对于源列表中的每个值
    • 如果结果列表中不存在该值,请将其添加到结果列表中
就这样

List<DataClass> result = new ArrayList<>();

for (DataClass item : dataList) {
    if (!result.contains(item)) {
        result.add(item);
    }
}
return result;
List result=new ArrayList();
用于(数据类项:数据列表){
如果(!result.contains(项)){
结果.添加(项目);
}
}
返回结果;
这假设
equals
方法的实现是固定的。 否则,
result.contains
步骤将无法正常工作

还要注意,
result.contains
执行线性搜索: 它检查每个项目,直到找到匹配项。 你可以提高性能
    linkedList.remove();