在Java中从列表中删除重复的对象
我知道以前很多时候都会问这种问题。但我的问题有点不同,我找不到任何类似的情况,所以在这里发布这个问题 问题: 我需要从ArrayList中删除重复的对象。我的arrayList的结构如下所示在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
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();