[英]In Java what is the quickest way to check if list contains items from another list, both list are of same type?
假设我有一个名为MyClass的类如下:
public class MyClass
{
//Identifier is alpha-numeric. If the identifier starts will 'ZZ'
//is special special identifier.
private String identifier = null;
//Date string format YYYY-MM-DD
private String dateString = null;
//Just a flag (not important for this scenario)
private boolean isCoolCat = false;
//Default Constructor and getters/setters implemented
//Overrides the standard Java equals() method.
//This way, when ArrayList calls contains() for MyClass objects
//it will only check the Date (for ZZ identifier)
//and identifier values against each other instead of
//also comparing the isCoolCat indicator value.
@Override
public boolean equals(Object obj)
{
if(this == obj)
{
return true;
}
if(obj == null)
{
return false;
}
if(getClass() != obj.getClass())
{
return false;
}
MyClass other = (MyClass) obj;
if(this.identifier == null)
{
if(other.identifier != null)
{
return false;
}
} else if(!this.identifier.equals(other.identifier)) {
return false;
}
if(other.identifier.startsWith("ZZ"))
{
if(!this.dateString.equals(other.dateString))
{
return false;
}
}
return true;
}
}
在另一个类中,我有两个MyClass类型的List, 每个类型包含100,000个对象 。 我需要检查一个列表中的项目是否在另一个列表中,我现在完成此操作如下:
`
List<MyClass> inList = new ArrayList<MyClass>();
List<MyClass> outList = new ArrayList<MyClass>();
inList = someMethodForIn();
outList = someMethodForOut();
//For loop iterates through inList and check if outList contains
//MyClass object from inList if it doesn't then it adds it.
for(MyClass inObj : inList)
{
if(!outList.contains(inObj))
{
outList.add(inObj);
}
}
我的问题是:这是实现这一目标的最快方法吗? 如果没有,你能否告诉我一个更好的实施,这将给我带来性能提升? 列表大小并不总是100,000。 目前在我的平台上,100,000个大小需要大约2分钟。 假设它可以从1到1,000,000不等。
你想为此使用Set
。 Set
有一个contains
方法,可以在O(1)时间内确定对象是否在集合中。
从List<MyClass>
转换为Set<MyClass>
时需要注意的几件事:
MyClass
需要实现hashcode()
和equals()
, 它们应该是一致的 。 要将List
转换为Set
您可以使用:
Set<MyObject> s1 = new HashSet<>(inList);
Set<MyObject> s2 = new HashSet<>(outList);
这篇Java文档解释了如何找到两个集合的并集,交集和差异。 特别是,你似乎对联盟感兴趣:
// transforms s2 into the union of s1 and s2. (The union of two sets
// is the set containing all of the elements contained in either set.)
s2.addAll(s1)
哈希! 哈希总是答案!
该代码的当前复杂度为O(nm)
,其中n
是inList
的大小, m
是outList
的大小。
您可以使用HashSet
将复杂度降低到O(n)
。 因为contains
现在需要O(1)
这可以这样做,
HashSet<MyClass> outSet = new HashSet<>(outList);
for(MyClass inObj : inList)
{
if(!outSet.contains(inObj))
{
outList.add(inObj);
}
}
信用和来源。
2分钟比较2个非常大的列表,可能不会节省太多时间,所以根据你的应用程序,你可以设置一个标志,以便依赖于此的东西不能运行,直到完成并将其推入它自己的线程并让用户做其他事情(同时也告诉他们这是正在进行的。)或者至少建立一个进度条。 让用户知道应用程序正在忙碌并且告诉他们(是啊)在一个非常复杂的计算中花费几分钟才会花费多长时间,这样就可以了,而且可能比仅仅刮几秒钟更好。 如果用户知道他们会有多长时间并且告诉他们有时间去喝咖啡,那么他们对延误非常宽容。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.