Guava Collection Utils与普通Java 7

时间:2016-05-19 09:51:21

标签: java collections guava

我经常试图使用Guava的集合utils编写代码,并在查看代码片段后发现自己在普通Java 7中重写代码,因为它使用普通的旧Java来更简洁,更容易阅读。 / p>

例如,将一个对象列表放入一个具有从对象中获取的唯一索引的地图中,使用Guava会看起来像这样:

 List<A> myList = ...
 Map<A, B> mappings = Maps.uniqueIndex(myList, new Function<A, B>() {
     @Override
     public CustomerFinance apply(final A input) {
         return input.getB();
     }
 });

而在vanilla Java 7中它将是:

List<A> myList = ...
Map<A, B> mappings = new HashMap<>(myList.size());
for (A a : myList) {
    mappings.put(a.getB(), a);
}

对于Guava中的映射(即使不计算@Override行)而言,这是普通Java中4个LOC的5个LOC。

为什么我要在这里使用Guava工具?首先创建utils的动机是什么?我错过了番石榴会为我提供的额外好处吗?

3 个答案:

答案 0 :(得分:3)

  

我是否错过了番石榴会为我提供的额外好处?

是的,你做了。

Guava有几个功能,你的翻译代码遗漏了(JavaDoc of Maps#uniqueIndex):

  • null禁止使用值(#)
  • null禁止使用密钥(对于给定值,密钥函数不应返回null
  • 禁止重复密钥(您不能意外覆盖现有密钥)
  • 生成的地图不可变

如果您也进行所有这些检查,那么您的代码应该比Guavas版本更长。

(#)请注意,您的翻译版本目前也禁止null,因为您在价值对象上调用#getB()。这将导致番石榴中的NullPointerException像。如果您从mappings.put(generateArtificalKey(), a);中的其他地方获取密钥,那么{7}将适用于Java 7版本。

另一个优点是关键功能的清洁代码。它可以很容易地移动到自己的类中并被重用。这方面的一个示例可能是提取数据库实体的id以创建具有该数据的地图的函数。但这是一个更多的意见,而不是事实,因为您的翻译代码(null循环)也可以被提取并用于其他情况。

答案 1 :(得分:2)

你可能会说,是的,就LOC而言,没有大的收获。然而,番石榴风格更多functional

转换函数可以传递并使用/重用。

 Function<A,B> map = new Function<A, B>() {
 @Override
 public CustomerFinance apply(final A input) {
     return input.getB();
 }

现在你可以传递地图并重复使用它而不是不同的地方。

Map<A, B> mappings = Maps.uniqueIndex(myList,map);
Map<C, D> mappings2 = Maps.uniqueIndex(myList,map);

但是,Guava仅限于Java 1.6构造,它没有为声明式样式提供最佳体验。

好消息是Guava中的Functionfunctional interface,所以如果你转到Java 1.8,你可以从第一天开始使用lambdas,你的代码看起来像这样,

Map<A, B> mappings = Maps.uniqueIndex(myList, input-> input.getB());

或者

Map<A, B> mappings = Maps.uniqueIndex(myList, A::getB);

答案 2 :(得分:1)

当我在8岁以上的Java版本中编程时,我通常会创建一个关联的实用程序类,以复数形式命名为实体,并将所有实用程序方法添加到其中。这样,我保持我的实体清洁,我可以访问一大堆实用程序方法。我没有系统地创建实用程序类,但仅在需要时才减少噪音。

public class MyEntity {
  private String text;
  public String getText() { return text; }
  public void setText (int text) { this.text = text; }
}

public final class MyEntities {
  private MyEntities() {}

  private enum MyEntityToString implements Function<MyEntity,String> {
    TEXT_GETTER {
      @Override public String apply(MyEntity input) { return input.getText(); }
    };
  }
  public static Function<MyEntity,String> textGetter() { return MyEntityToString.TEXT_GETTER; }
}

然后,使用变得像在需要时使用方法MyEntities.textGetter()一样简单。如果你只使用它一次,是的,你就失去了LOC,但如果你多次使用它,你就赢了。此外,如果你有一个错误,你只需要修复一次,而不是找到每个用途来修复它。