如何在Java中访问List的第一个非null项?

时间:2016-04-07 17:18:54

标签: java list oop null java-8

所以我有一个方法(我不能更改参数,否则这可以通过HashMaps更容易...稍后会详细介绍),将项目作为参数传递。现在我有一个来自这个其他类的实例列表,其中一个属性与此项的类型相同,我想在列表中找到与该项对应的实例(其中应该只有一个)。这就是我做的事情:

List<Instance> instances = ...

public static void checkItems(Item i) {

    List<Instance> n = new ArrayList<>();
    instances.forEach(p -> n.add(p.i == i ? p : null));

    Instance currentInstance = n.get(0); 
    //Instance currentInstance = instances.stream().filter(p -> p.i == i).collect(Collectors.toList()).get(0);

}

你可能会注意到两件事:

  1. 我使用了一个条件运算符,它在条件未通过时向列表添加空值
  2. 我评论的代码是解决此问题的另一种尝试
  3. 所以在第一种情况下,我把null放在因为它需要你放东西,而且一个空值可能更容易使用,这就是出现问题的原因:我如何访问第一个非空值列表(不需要遍历整个列表来查找它...)?

    您可能会注意到我只是将列表的第一个值n.get(0)分配给currentInstance,因为我知道只有一个值会通过测试。但是,由于我应用于currentInstance的其他一些代码,此值不能为空。

    关于第二点的注释:我试图用流解决它的方式实际上完全按计划工作,除了由于某种原因恢复的实例列表不是原始实例的直接副本。这导致某些属性的值已重置为默认值,因此使此方法无效。

    编辑:我只是想提一下,由于我在另一个类中犯了一些愚蠢的错误,因为我没有使用它,因此我会使用那个位来解决我的问题: d

4 个答案:

答案 0 :(得分:4)

如果您知道只有一个p通过了测试,我不知道创建一个加载null值加p的列表是什么意思。

您的问题似乎源于想要使用forEach。在我看来,你应该almost always use a for loop in preference to forEach。使用简单的for循环,您可以在找到项目时使用break

详细说明:

Instance p = null;
for (Instance q : instances) {
    if (q.i == i) {
        p = q;
        break;
    }
}
if (p == null)
    throw new IllegalStateException();   // It wasn't there.
// Do something with p.

答案 1 :(得分:3)

你可以这样做:

Instance currentInstance = instances.stream()
    .filter(p -> p.i == i)
    .findFirst()
    .get(); // you can use get if you are sure there's one instance

谓词p -> p.i == i似乎很可疑。为什么不使用equals()

答案 2 :(得分:3)

如上所述,通常可以通过以下方式解决流:

Optional<Instance> first =
    instances.stream().filter(p -> p.i == i).findFirst();
  

(其中应该只有一个)

其中肯定只有一个,或可能多个。 (如果有多个,那么什么?这是一个错误吗?)听起来你可能应该有一个Set<Instance>,而不是List<Instance>。只是观察。

答案 3 :(得分:2)

你可以这样做

instances.forEach(p -> {
   if (p.i == i) n.add(p);
});