繁体   English   中英

在Java中,检查列表是否包含来自另一个列表的项目的最快方法是什么,两个列表的类型相同?

[英]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>时需要注意的几件事:

  1. 你将失去元素的顺序
  2. 您将丢失重复的元素
  3. 你的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) ,其中ninList的大小, moutList的大小。

您可以使用HashSet将复杂度降低到O(n) 因为contains现在需要O(1)

这可以这样做,

   HashSet<MyClass> outSet = new HashSet<>(outList);
   for(MyClass inObj : inList)
   {
        if(!outSet.contains(inObj))
        {
              outList.add(inObj); 
         }
    }

信用和来源。

返回java中两个列表之间的差异

在对象的ArrayList中包含(Object o)的时间复杂度

HashSet.contains性能

2分钟比较2个非常大的列表,可能不会节省太多时间,所以根据你的应用程序,你可以设置一个标志,以便依赖于此的东西不能运行,直到完成并将其推入它自己的线程并让用户做其他事情(同时也告诉他们这是正在进行的。)或者至少建立一个进度条。 让用户知道应用程序正在忙碌并且告诉他们(是啊)在一个非常复杂的计算中花费几分钟才会花费多长时间,这样就可以了,而且可能比仅仅刮几秒钟更好。 如果用户知道他们会有多长时间并且告诉他们有时间去喝咖啡,那么他们对延误非常宽容。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM