如何将不存在的值从 arrayList2 添加到 arrayList1?

How do I add non-existing values in from arrayList2 to arrayList1?

假设我有一个点数组列表 1。数据结构是这样的:

(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++;

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

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

这意味着你可以在你的Set中添加很多List,你不会有重复的。

    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]

你可以这样做

    list2.removeAll(list1);
    list1.addAll(list2);

你必须在你的积分中覆盖你的平等功能Class

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

How do I compare the two lists

那个很简单,用等号就可以了。

add non-existing values from arrayList2 to 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
}

Is there a more efficient way

一点建议:
首先,让它发挥作用(并具有良好的单元测试覆盖率)。然后(并且只有那时!)根据需要进行优化!

如果时间复杂度是您的首要任务,请将List1中的所有点添加到HashSet<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

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

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

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

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

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

  1. 单线爱好者 (running demo):

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

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

    * 正如 Bruce Wayne 正确指出的那样,Double Brace initialization(单行示例,在两个示例中也用于填充前两个列表)应谨慎使用,因为所描述的潜在缺点在以下文章中:

    Don’t be “Clever”: The Double Curly Braces Anti Pattern

解释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);

Output: [One, Two, Three]

示例 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);

Output: [One, Two, Three]