Java 谷歌收藏供应商和查找

Java 谷歌收藏供应商和查找,java,guava,Java,Guava,我正在寻找一个Google Collections方法,它返回不返回null的供应商序列的第一个结果 我正在考虑使用Iterables.find,但是在我的谓词中,我必须调用我的supplier将结果与null进行比较,然后在find方法返回supplier后再次调用它。这有什么问题 List<Supplier> supplierList = //somehow get the list Supplier s = Iterables.find(supplierList, new Pr

我正在寻找一个Google Collections方法,它返回不返回null的供应商序列的第一个结果


我正在考虑使用Iterables.find,但是在我的谓词中,我必须调用我的supplier将结果与null进行比较,然后在find方法返回supplier后再次调用它。

这有什么问题

List<Supplier> supplierList = //somehow get the list
Supplier s = Iterables.find(supplierList, new Predicate<Supplier>(){
     boolean apply(Supplier supplier) {
         return supplier.isSomeMethodCall() == null;
     }
     boolean equals(Object o) {
         return false;
     }
});
你想保存一些线路吗?我认为唯一的优化就是静态导入这个发现,这样你就可以摆脱Iterables了。谓词也是一个匿名的内部类,如果您在多个地方需要它,您可以创建一个类

List<Supplier> supplierList = //somehow get the list
Supplier s = find(supplierList, new SupplierPredicateFinder());
其中SupplierPredicateFinder是另一个类

更新:在这种情况下,find是错误的方法。实际上,您需要这样一个自定义函数,它可以返回两个值。如果您使用的是commons集合,则可以使用DefaultMapEntry,也可以只返回对象[2]或Map.Entry

public static DefaultMapEntry getSupplier(List<Supplier> list) {
    for(Supplier s : list) {
        Object heavyObject = s.invokeCostlyMethod();
        if(heavyObject != null) {
             return new DefaultMapEntry(s, heavyObject);
        }
    }
}

用大小为2的列表或大小为1的哈希映射或长度为2的数组替换DefaultMapEntry:

这有什么问题

List<Supplier> supplierList = //somehow get the list
Supplier s = Iterables.find(supplierList, new Predicate<Supplier>(){
     boolean apply(Supplier supplier) {
         return supplier.isSomeMethodCall() == null;
     }
     boolean equals(Object o) {
         return false;
     }
});
你想保存一些线路吗?我认为唯一的优化就是静态导入这个发现,这样你就可以摆脱Iterables了。谓词也是一个匿名的内部类,如果您在多个地方需要它,您可以创建一个类

List<Supplier> supplierList = //somehow get the list
Supplier s = find(supplierList, new SupplierPredicateFinder());
其中SupplierPredicateFinder是另一个类

更新:在这种情况下,find是错误的方法。实际上,您需要这样一个自定义函数,它可以返回两个值。如果您使用的是commons集合,则可以使用DefaultMapEntry,也可以只返回对象[2]或Map.Entry

public static DefaultMapEntry getSupplier(List<Supplier> list) {
    for(Supplier s : list) {
        Object heavyObject = s.invokeCostlyMethod();
        if(heavyObject != null) {
             return new DefaultMapEntry(s, heavyObject);
        }
    }
}

将DefaultMapEntry替换为大小为2的列表或大小为1的hashmap或长度为2的数组:

鉴于您对平息Storm回答的意见,希望不要给供应商打两次电话,那么:

private static final Function<Supplier<X>, X> SUPPLY = new Function<....>() {
    public X apply(Supplier<X> in) {
        // If you will never have a null Supplier, you can skip the test;
        // otherwise, null Supplier will be treated same as one that returns null
        // from get(), i.e. skipped
        return (in == null) ? null : in.get();
    }
}
然后


请注意,Iterables.transform中的Iterable是惰性计算的,因此作为Iterables.find循环,您只计算第一个返回的非空值,并且只计算一次。

鉴于您对Calm Storm答案的评论,希望不要给供应商打电话。获得两次,那么:

private static final Function<Supplier<X>, X> SUPPLY = new Function<....>() {
    public X apply(Supplier<X> in) {
        // If you will never have a null Supplier, you can skip the test;
        // otherwise, null Supplier will be treated same as one that returns null
        // from get(), i.e. skipped
        return (in == null) ? null : in.get();
    }
}
然后


请注意,Iterables.transform中的Iterable是惰性计算的,因此作为Iterables.find循环,您只计算第一个返回非null的循环,并且只计算一次。

您询问了如何使用Google Collections进行此操作,但以下是您在不使用Google Collections的情况下的操作方法。将其与考恩的答案进行比较,考恩的答案是一个好的答案——哪一个更容易理解

private static Thing findThing(List<Supplier<Thing>> thingSuppliers) {
  for (Supplier<Thing> supplier : thingSuppliers) {
    Thing thing = supplier.get();
    if (thing != null) {
      return thing;
    }
  }
  // throw exception or return null
}

代替注释-如果这是类调用方的错误,则根据需要抛出IllegalArgumentException或IllegalStateException;如果这不应该发生,请使用AssertionError;如果调用此项的代码需要检查的是正常情况,则可能会返回null。

您询问如何使用Google Collections执行此操作,但以下是您在不使用Google Collections的情况下执行此操作的方法。将其与考恩的答案进行比较,考恩的答案是一个好的答案——哪一个更容易理解

private static Thing findThing(List<Supplier<Thing>> thingSuppliers) {
  for (Supplier<Thing> supplier : thingSuppliers) {
    Thing thing = supplier.get();
    if (thing != null) {
      return thing;
    }
  }
  // throw exception or return null
}

代替注释-如果这是类调用方的错误,则根据需要抛出IllegalArgumentException或IllegalStateException;如果这不应该发生,请使用AssertionError;如果调用此函数的代码需要检查的是正常情况,则可能返回null。

在Google Collections界面上有一个名为get的方法。在这种情况下,这是一个耗时的计算。当谓词匹配时,Iterables.find返回供应商,而不是get的结果。所以在find的结果之后,我需要再次调用get,它需要再次执行计算。我可以使用MemorizingSupplier,但如果find方法返回的是供应商的结果,而不是供应商本身,那就更好了。这个答案不连贯。根据原文提出的问题,前半部分无效。在下半部分,当用户只需要heavyObject时,为什么同时返回供应商和heavyObject?我很担心我们会这么快推荐地图。Entry/Object[2]黑客攻击,对任何人来说,这都是一种怪诞的黑客攻击,除非真正需要。我觉得我应该继续解释更多,因为我投了反对票:还有,问题是关于gc的Supplier类的,您似乎从来没有看过它,您会发现它是泛型的,并且有一个名为get的方法。最后一个方法没有编译结尾处预期的返回语句。我只是说,所有这些小问题加起来都不是很有用的答案。问题是关于gc的供应商类别的——询问者没有明确说明这一点。我只是假设这是他的域类。你的上一个方法没有编译-我想展示
一般结构而不是可以粘贴到IDE中的现成代码。根据原始问题的文本,前半部分是无效的。-这个问题是在我的回答后编辑的。请看Cowan的回答和我的参考。在供应商的Google Collections界面上,有一个名为get的方法。在这种情况下,这是一个耗时的计算。当谓词匹配时,Iterables.find返回供应商,而不是get的结果。所以在find的结果之后,我需要再次调用get,它需要再次执行计算。我可以使用MemorizingSupplier,但如果find方法返回的是供应商的结果,而不是供应商本身,那就更好了。这个答案不连贯。根据原文提出的问题,前半部分无效。在下半部分,当用户只需要heavyObject时,为什么同时返回供应商和heavyObject?我很担心我们会这么快推荐地图。Entry/Object[2]黑客攻击,对任何人来说,这都是一种怪诞的黑客攻击,除非真正需要。我觉得我应该继续解释更多,因为我投了反对票:还有,问题是关于gc的Supplier类的,您似乎从来没有看过它,您会发现它是泛型的,并且有一个名为get的方法。最后一个方法没有编译结尾处预期的返回语句。我只是说,所有这些小问题加起来都不是很有用的答案。问题是关于gc的供应商类别的——询问者没有明确说明这一点。我只是假设这是他的域类。你的上一个方法没有编译-我试图展示一个通用的结构,而不是一个可以粘贴到IDE中的现成代码。根据原始问题的文本,前半部分是无效的该问题是在我的回答后编辑的。请参阅Cowan的回答和我的参考文献+1,以便很好地回答所问的问题。尽管如此,我认为问题应该是什么是最好的解决方法,而不是什么是使用谷歌收藏的解决方法,所以我提供了另一个答案。接受这个问题,因为它回答了最初的问题,但也阅读了凯文的评论。+1很好地回答了问题。尽管如此,我认为问题应该是什么是最好的解决方法,而不是什么是使用谷歌收藏的解决方法,所以我提供了另一个答案。接受这个答案,因为它回答了最初的问题,但也阅读了凯文的评论。这是我最初的解决方案,我真的应该在问题中发布它。然而,随着我们发现谓词和函数的一些很好的用途,我想看看是否存在类似Suppliers.firstSupplied的东西。正如Cowan的工作建议所示,这可能是Java中的函数式导致代码不易理解的情况。两种解决方案都通过了测试。这是我最初的解决方案,我真的应该在问题中发布它。然而,随着我们发现谓词和函数的一些很好的用途,我想看看是否存在类似Suppliers.firstSupplied的东西。正如Cowan的工作建议所示,这可能是Java中的函数式导致代码不易理解的情况。两种解决方案都通过了测试。