我经常试图使用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的动机是什么?我错过了番石榴会为我提供的额外好处吗?
答案 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中的Function
是functional 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,但如果你多次使用它,你就赢了。此外,如果你有一个错误,你只需要修复一次,而不是找到每个用途来修复它。