2

晚上好,我有一个简单的任务,就是在两个列表中找到共同的数字。但我有一个疯狂的错误。我傻眼了,因为我无法想象可能出了什么问题。

public class Test {

    public static List<Integer> same(List<Integer> a1, List<Integer> a2){

        List<Integer> lister = new ArrayList<>();

        for(int i = 0; i < a1.size() ; i++){
            for(int j = 0; j < a2.size(); j++){
                System.out.print(a1.get(i) + " vs " + a2.get(j));
                if(a1.get(i) == a2.get(j)){
                    System.out.print("equals");
                    lister.add(a2.get(j));
                }
                System.out.println();
            }
        }
        return lister;
    }


    public static void main(String[] args) {
        // TODO Auto-generated method stub

        Scanner in = new Scanner(System.in);

        int n = in.nextInt();

        List<Integer> list1 = new ArrayList<>();

        for (int i = 0; i < n; i++) {
            list1.add(in.nextInt());
        }

        System.out.println();
        int m = in.nextInt();

        List<Integer> list2 = new ArrayList<>();

        for (int i = 0; i < m; i++) {
            list2.add(in.nextInt());
        }

        List<Integer> result = same(list1,list2);

        System.out.println(result.size());

        in.close();

    }

}

输入 :

5 13 20 22 43 146 4 13 22 43 146

输出 :

13 vs 13equals
13 vs 22
13 vs 43
13 vs 146
20 vs 13
20 vs 22
20 vs 43
20 vs 146
22 vs 13
22 vs 22equals
22 vs 43
22 vs 146
43 vs 13
43 vs 22
43 vs 43equals
43 vs 146
146 vs 13
146 vs 22
146 vs 43
146 vs 146
3

所以 146 != 146 。我的错误在哪里?

谢谢。

4

4 回答 4

7

这是一个有趣的问题。如果 Integer 或 Long 等包装类的值介于 -128 和 128 之间,则它们将保存在池中。使用 == 运算符可以比较两个变量在堆栈中的位置。如果它们在池中,则此位置相同。如果您比较的值高于 128,则您正在比较两个不同 Integer 对象的位置。这就是为什么你需要使用 equals 方法。

于 2013-04-26T15:37:02.563 回答
7

您正在存储Integer对象,然后将它们与==

因为它们是引用类型,所以 == 比较对象引用。

而是使用if(a1.get(i).intValue() == a2.get(j).intVaue() ){

或者if(a1.get(i).equals(a2.get(j))

编辑

@Templar 很好地解释了为什么对象引用比较适用于 128 以下的数字。

为了清楚起见,这里是谈论它的实际JLS 。

如果被装箱的值 p 是真、假、一个字节或 \u0000 到 \u007f 范围内的一个字符,或者一个介于 -128 和 127(含)之间的 int 或短数字,则令 r1 和 r2 为p 的任意两个拳击转换。r1 == r2 总是如此。

于 2013-04-26T15:34:43.500 回答
3

试试这个例子。

public static void main(String[] args) {
    List<Integer> listOne = Arrays.asList(1, 2, 3, 4, 5, 6);
    List<Integer> listTwo = Arrays.asList(1, 2, 3);

    Set<Integer> similar = new HashSet<Integer>(listOne);
    Set<Integer> different = new HashSet<Integer>();
    different.addAll(listOne);
    different.addAll(listTwo);

    similar.retainAll(listTwo);
    different.removeAll(similar);
    System.out.println("Similar  " + similar);
    System.out.println("Different  " + different);
}

输出:

Similar  [1, 2, 3]
Different  [4, 5, 6]
于 2013-04-26T15:29:13.610 回答
0

==就像其他人说的那样,除非你真的想比较它们在内存中的位置,否则不要用来比较对象引用。

您的方法的主体可以使用Google Guava作为单行代码进行重写:

public List<Integer> same(List<Integer> list1, List<Integer> list2) {
    return Lists.newArrayList(Sets.intersection(
        ImmutableSet.copyOf(list1), ImmutableSet.copyOf(list2)));
}

启动也是 O(n + m) 而不是 O(nm)。

于 2013-04-26T16:00:07.467 回答