3

假设我有一个点的arrayList1。数据结构是这样的:

(1,2)->(2,2)->(3,2)->(4,2)->(5,2)

我有另一个 arrayList2 点:

(2,2)->(1,2)->(8,5)->(9,3)

如何比较两个列表并将 arrayList2 中的不存在值添加到 arrayList1?

当前解决方案

我现在能想到的唯一方法是使用 for 循环来比较 arrayList1 中的每个点,例如if(!arrayList1.contains(arrayList2.get(i))){ arrayList1.add(arrayList2.get(i)); } i++;.

有没有更有效的方法或已经准备好的方法?因为我有 arrayList1 直到 arrayList6 来比较和替换....

4

7 回答 7

4
  1. 对于单线爱好者运行演示):

    List<Point> list3 = new ArrayList<Point>(new HashSet<Point>(list1){{ addAll(list2); }});
    
  2. 安全版*运行演示):

    Set<String> tmpSet = new HashSet<String>(arrayList1);
    tmpSet.addAll(arrayList2);
    List<String> mergedList = new ArrayList<String>(tmpSet);
    

    * 正如 Bruce Wayne 正确指出的那样,由于以下文章中描述的潜在缺点,应谨慎使用双括号初始化(单行示例,也用于两个示例以填充前两个列表):

    不要“聪明”:双花括号反模式

解释Sets 不能包含重复项,所以使用一个作为转换向量。

示例 1 代码:

List<String> arrayList1 = new ArrayList<String>(){{ add("One"); add("Two");   }};
List<String> arrayList2 = new ArrayList<String>(){{ add("Two"); add("Three"); }};   
List<String> mergedList = new ArrayList<String>(new HashSet<String>(arrayList1){{ addAll(arrayList2); }});
System.out.println(mergedList);

输出:[一、二、三]

示例 2 代码:

List<String> arrayList1 = new ArrayList<String>(){{ add("One"); add("Two");   }}; 
List<String> arrayList2 = new ArrayList<String>(){{ add("Two"); add("Three"); }}; 
Set<String> tmpSet = new HashSet<String>(arrayList1);
tmpSet.addAll(arrayList2);
List<String> mergedList = new ArrayList<String>(tmpSet);
System.out.println(mergedList);

输出:[一、二、三]

于 2015-05-27T12:42:00.543 回答
2

如果时间复杂度是您的主要优先事项,请将所有点添加List1HashSet<Point>.

然后,对于之后的每个列表,循环遍历它并查看集合是否包含每个点,如果不包含,则将其添加到List1.

Set<Point> pointsInList1 = new HashSet<>(list1);
for(Point p : list2)
{
    if(!pointsInList1.contains(p)) {
        list1.add(p);
        pointsInList1.add(p);
    }
}

//Repeat for other lists

该解决方案与最大列表的大小成线性关系。

于 2015-05-27T12:19:44.203 回答
1

您应该使用Set. 这是一个没有重复的集合。所以你可以添加两次相同的值,它只会出现一次。

这意味着您可以List在中添加许多,其中Set不会有重复项。

    Set setA = new HashSet(); 

    ArrayList<Point> points1 = new ArrayList<Point>();
    ArrayList<Point> points2 = new ArrayList<Point>();

    Point element1 = new Point(0,0);
    Point element2 = new Point(0,1);
    Point element3 = new Point(0,0);
    Point element4 = new Point(0,2);

    points1.add(element1); 
    points1.add(element2); 
    points1.add(element3);

    points2.add(element1);
    points2.add(element4);

    setA.addAll(points1);
    setA.addAll(points2);

    Iterator<Point> it = setA.iterator();
    while(it.hasNext())
        System.out.println(it.next());

输出 :

java.awt.Point[x=0,y=0]
java.awt.Point[x=0,y=1]
java.awt.Point[x=0,y=2]
于 2015-05-27T12:15:28.403 回答
1

它可以有多种解决方案。当您使用java.awt.Point已经equals覆盖了方法的类(基于坐标)时。因此,您可以轻松地使用类contains方法List

for(Point point : list2){
     if(!list1.contains(point)){
         list1.add(point);
     }
}

确保使用for each循环以获得更好的性能(不要使用基于索引的循环(如果您使用它会有所不同LinkedList))。

ii) 另一种选择是使用java.util.Set和使用它的方法addAll(Set)。由于 Set 并非所有重复,因此将有效地合并元素。

于 2015-05-27T12:22:28.943 回答
0

你可以做这样的事情

    list2.removeAll(list1);
    list1.addAll(list2);
于 2015-05-27T12:15:39.287 回答
0

你必须在你的 Point Class 中覆盖你的 equal 函数

然后你可以遍历这两个列表,并比较它们的值。

于 2015-05-27T12:16:28.070 回答
0

如何比较两个列表

那很简单,只需使用equals。

将 arrayList2 中不存在的值添加到 arrayList1

  • 从arrayList2 中删除arrayList1 的所有元素并将其添加到arrayList2。这样只会将新元素添加到 arrayList2
  • 获取差异 (arrayList1 - arrayList2) 并将它们添加到 arrayList2 (例如使用CollectionUtils )

您当前的解决方案可能是错误的(它会跳过一个元素或永远运行,具体取决于您的循环):

if(arrayList1.contains(arrayList2.get(i))) {
  i++; // this shouldn't be there if done in the loop
} else {
  arrayList1.add(arrayList2.get(i)); // here a ++ is needed if not in the loop
}

有没有更有效的方法

一个小建议:
首先,让它工作(并有一个良好的 UnitTest 覆盖率)。然后(只有那时!)如果需要优化!

于 2015-05-27T12:17:36.927 回答