2

我正在尝试检查 long 列表是否不包含某个值。似乎这个条件永远不会满足,即使我知道某个链表中不存在一个值......

for(int i : organizationIDs){
    if(!ListOfOrgIds.contains(Long.valueOf(i))){
        addThese.add(new Long(i));
    }
}

我本质上是在寻找 orgID 数组中不存在的值,如果它不存在,请将其添加到addThese链接列表中......我是否错过了我应该知道的 Long 的一些细微差别?

在调试器中找到的 ListOfOrgIds

14057
821
18021

在调试器中找到的组织 ID

821
14057
18021

让我这么说吧,我正看着调试器,它告诉我这 ListOfOrgIds.contains(i) 是错误的......这显然是不真实的......在此处输入图像描述

具体来说,看看 ListOfOrgs 的值...

在此处输入图像描述

821确实在里面。为什么我在 contains 调用中得到错误消息?

4

2 回答 2

2

您遇到的问题是java不允许将原语加宽然后装箱,只能装箱然后加宽。这意味着 int 不能成为 Long,但 int 可以成为 Object(通过 Integer)。这个问题的最佳答案很好地描述了它。在这种情况下,您不会得到任何编译反馈,因为 contains 方法不使用 list 的类型参数,它接受任何对象。这在过去也让我很多次。

下面是一个SSCCE,显示了您获得的结果和一个工作示例。请注意,只需将 int 显式转换为 long。

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class BoxingTest {

    public static void main(String[] args) throws Exception {

        List<Integer> intList = Arrays.asList(new Integer[]{14, 24, 69});
        List<Long> sourceLongList = Arrays.asList(new Long[]{14L, 17L});

        List<Long> resultsList;
        /* Test as in question code */
        resultsList = new ArrayList<Long>();
        for(int i : intList){
            if(!sourceLongList.contains(i)){
                resultsList.add(new Long(i));
            }
        }
        printList(resultsList);

        /* Can't box then widen, so cast */
        resultsList = new ArrayList<Long>();
        for(int i : intList){
            if(!sourceLongList.contains((long)i)){
                resultsList.add(new Long(i));
            }
        }
        printList(resultsList);

    }

    private static <T> void printList(List<T> values){
        StringBuilder contents = new StringBuilder();
        for(T value : values){
            contents.append(value);
            contents.append(" ");
        }
        System.out.println("List contains: " + contents);
    }

}
于 2012-09-25T21:13:50.077 回答
1

我想说的第一点是,您似乎最好使用Set它,因为它不允许重复元素。换句话说,做:

Set<Long> ids = new HashSet<Long>();
ids.add(Long.valueOf(1));
ids.add(Long.valueOf(1));
System.out.println(ids.size());

会打印1,不像2会打印List

我不确定您要查找的确切操作,但您需要三种可能的操作:并集、交集和相对补集。有关它们的正式定义和维恩图,请参阅Set 页面上的此 Wikipedia 部分

联盟

结果:所有元素都在A并且B将在C.

要执行此操作:

Set<Long> a = ... ;
Set<Long> b = ... ;
Set<Long> c = new HashSet<Long>(a);
c.addAll(b);

路口

结果:只有两者中的元素AB将在C.

要执行此操作:

Set<Long> a = ... ;
Set<Long> b = ... ;
Set<Long> c = new HashSet<Long>(a);
c.retainAll(b);

相对补

结果:C将包含除中的元素A之外的所有元素B

要执行此操作:

Set<Long> a = ... ;
Set<Long> b = ... ;
Set<Long> c = new HashSet<Long>(a);
c.removeAll(b);

此外,要将 a 转换List为 a Set

List<Long> idsAsList = ... ;
Set<Long> idsAsSet = new HashSet<Long>(idsAsList);

要将数组转换为 a Set,您必须根据是否有 along[]或 a来做不同的事情Long[](注意大写)。对于long[],您必须手动复制:

long[] idsAsArray = ... ;
Set<Long> idsAsSet = new HashSet<Long>();
for (long l : idsAsArray) {
    idsAsSet.add(Long.valueOf(l));
}

如果是Long[],您可以使用Arrays.asList

Long[] idsAsArray = ... ;
Set<Long> ids = new HashSet<Long>(Arrays.asList(idsAsArray));
于 2012-09-25T18:27:01.137 回答