I am often tempted to write code using Guava's collection utils and find myself rewriting the code in plain Java 7 after looking at the code fragment, because it IMHO turns out to be more concise and easier to read using plain old Java.
我经常试图使用Guava的集合utils编写代码,并在查看代码片段后发现自己在普通Java 7中重写代码,因为它使用普通的旧Java更简洁,更容易阅读。
For instance putting a list of objects into a map with a unique index taken from the objects would look something like this using Guava:
例如,将对象列表放入带有从对象中获取的唯一索引的地图中,使用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();
}
});
whereas in vanilla Java 7 it would be:
而在香草Java 7中它将是:
List<A> myList = ...
Map<A, B> mappings = new HashMap<>(myList.size());
for (A a : myList) {
mappings.put(a.getB(), a);
}
That's 5 LOC's for the mapping in Guava (even not counting the @Override
line) versus 4 LOC's in plain Java.
这是Guava中映射的5个LOC(甚至不计算@Override行)与普通Java中的4个LOC。
Why should I use the Guava utils here? What was the incentive in creating the utils in the first place? Am I missing some added benefit that Guava will provide me?
我为什么要在这里使用Guava工具?首先创建utils的动机是什么?我错过了番石榴会为我提供的一些额外好处吗?
3 个解决方案
#1
3
Am I missing some added benefit that Guava will provide me?
我错过了番石榴会为我提供的一些额外好处吗?
Yes you do.
是的你是。
There are several features in Guava which your translated code misses (JavaDoc of Maps#uniqueIndex):
Guava中有几个功能,您的翻译代码未命中(JavaDoc of Maps#uniqueIndex):
-
null
for values is prohibited (#) -
null
for keys is prohibited (the key function shouldn't returnnull
for a given value) - duplicate keys are prohibited (you can't unexpectedly overwrite existing keys)
- the resulting map is immutable
禁止值为null(#)
禁止使用null(对于给定值,键函数不应返回null)
禁止重复键(您不能意外覆盖现有键)
生成的映射是不可变的
If you would all these checks as well, then your code should be a longer than Guavas version.
如果您也进行所有这些检查,那么您的代码应该比Guavas版本更长。
(#) Mind, that your translated version currently prohibits null
as well, because you call #getB()
on your value object. This will cause a NullPointerException
like in Guava. If you would get the key from somewhere else like in mappings.put(generateArtificalKey(), a);
, then null
would be fine for the Java 7 version.
(#)请注意,您的翻译版本目前也禁止null,因为您在值对象上调用#getB()。这将导致像Guava中的NullPointerException。如果您从其他地方获取密钥,例如在mappings.put(generateArtificalKey(),a);中,那么对于Java 7版本,null就可以了。
Another advantage is the cleaner code of the key function. It can be easily moved into an own class and be reused. An example for that might be a function which extracts the id of database entities to create a map with that. But this is a more an opinion, than a fact since your translated code (the for
loop) can also be extracted and used for other cases.
另一个优点是关键功能的清洁代码。它可以很容易地移动到自己的类中并被重用。一个例子可能是一个提取数据库实体的id以创建具有该数据的地图的函数。但这是一个更多的意见,而不是事实,因为您的翻译代码(for循环)也可以被提取并用于其他情况。
#2
2
You might argue that yes, there is not a big gain in terms of LOC's. However, the Guava style is more functional
.
你可能会说,是的,就LOC而言,没有大的收获。然而,番石榴风格更具功能性。
The transform function can be passed around and used/reused.
转换函数可以传递并使用/重用。
Function<A,B> map = new Function<A, B>() {
@Override
public CustomerFinance apply(final A input) {
return input.getB();
}
Now you can pass map around and reuse it not different places.
现在你可以传递地图并重复使用它而不是不同的地方。
Map<A, B> mappings = Maps.uniqueIndex(myList,map);
Map<C, D> mappings2 = Maps.uniqueIndex(myList,map);
But then again, Guava
is limited to Java 1.6 constructs, which doesn't give the best experience for declarative style.
但话说回来,Guava仅限于Java 1.6构造,它没有为声明式样式提供最佳体验。
The good news is that Function
in Guava is a functional interface
, so if you move to Java 1.8, you can start using lambdas from day one, and your code will look like this,
好消息是,Guava中的Function是一个功能界面,所以如果你转到Java 1.8,你可以从第一天开始使用lambdas,你的代码看起来像这样,
Map<A, B> mappings = Maps.uniqueIndex(myList, input-> input.getB());
Or
Map<A, B> mappings = Maps.uniqueIndex(myList, A::getB);
#3
1
When I program in versions of Java older than 8, I usually create an associated utility class, named as the entity but in plural form, and add all the utility method to it. This way, I keep my entities clean and I have access to a large panel of utility methods. I don't systematically create a utility class, but only when needed to reduce noise.
当我在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; }
}
Then, the usage becomes as simple as using the method MyEntities.textGetter()
when needed. If you use it only once, yes, you lose in terms of LOCs, but if you use it several times, you just win. Also, if you ever have a bug, you have to fix it only once and not find every usage to fix it everywhere.
然后,使用变得像在需要时使用方法MyEntities.textGetter()一样简单。如果你只使用它一次,是的,你就失去了LOC,但如果你多次使用它,你就赢了。此外,如果你有一个错误,你只需要修复一次,而不是找到每个用途来解决它到处都是。
#1
3
Am I missing some added benefit that Guava will provide me?
我错过了番石榴会为我提供的一些额外好处吗?
Yes you do.
是的你是。
There are several features in Guava which your translated code misses (JavaDoc of Maps#uniqueIndex):
Guava中有几个功能,您的翻译代码未命中(JavaDoc of Maps#uniqueIndex):
-
null
for values is prohibited (#) -
null
for keys is prohibited (the key function shouldn't returnnull
for a given value) - duplicate keys are prohibited (you can't unexpectedly overwrite existing keys)
- the resulting map is immutable
禁止值为null(#)
禁止使用null(对于给定值,键函数不应返回null)
禁止重复键(您不能意外覆盖现有键)
生成的映射是不可变的
If you would all these checks as well, then your code should be a longer than Guavas version.
如果您也进行所有这些检查,那么您的代码应该比Guavas版本更长。
(#) Mind, that your translated version currently prohibits null
as well, because you call #getB()
on your value object. This will cause a NullPointerException
like in Guava. If you would get the key from somewhere else like in mappings.put(generateArtificalKey(), a);
, then null
would be fine for the Java 7 version.
(#)请注意,您的翻译版本目前也禁止null,因为您在值对象上调用#getB()。这将导致像Guava中的NullPointerException。如果您从其他地方获取密钥,例如在mappings.put(generateArtificalKey(),a);中,那么对于Java 7版本,null就可以了。
Another advantage is the cleaner code of the key function. It can be easily moved into an own class and be reused. An example for that might be a function which extracts the id of database entities to create a map with that. But this is a more an opinion, than a fact since your translated code (the for
loop) can also be extracted and used for other cases.
另一个优点是关键功能的清洁代码。它可以很容易地移动到自己的类中并被重用。一个例子可能是一个提取数据库实体的id以创建具有该数据的地图的函数。但这是一个更多的意见,而不是事实,因为您的翻译代码(for循环)也可以被提取并用于其他情况。
#2
2
You might argue that yes, there is not a big gain in terms of LOC's. However, the Guava style is more functional
.
你可能会说,是的,就LOC而言,没有大的收获。然而,番石榴风格更具功能性。
The transform function can be passed around and used/reused.
转换函数可以传递并使用/重用。
Function<A,B> map = new Function<A, B>() {
@Override
public CustomerFinance apply(final A input) {
return input.getB();
}
Now you can pass map around and reuse it not different places.
现在你可以传递地图并重复使用它而不是不同的地方。
Map<A, B> mappings = Maps.uniqueIndex(myList,map);
Map<C, D> mappings2 = Maps.uniqueIndex(myList,map);
But then again, Guava
is limited to Java 1.6 constructs, which doesn't give the best experience for declarative style.
但话说回来,Guava仅限于Java 1.6构造,它没有为声明式样式提供最佳体验。
The good news is that Function
in Guava is a functional interface
, so if you move to Java 1.8, you can start using lambdas from day one, and your code will look like this,
好消息是,Guava中的Function是一个功能界面,所以如果你转到Java 1.8,你可以从第一天开始使用lambdas,你的代码看起来像这样,
Map<A, B> mappings = Maps.uniqueIndex(myList, input-> input.getB());
Or
Map<A, B> mappings = Maps.uniqueIndex(myList, A::getB);
#3
1
When I program in versions of Java older than 8, I usually create an associated utility class, named as the entity but in plural form, and add all the utility method to it. This way, I keep my entities clean and I have access to a large panel of utility methods. I don't systematically create a utility class, but only when needed to reduce noise.
当我在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; }
}
Then, the usage becomes as simple as using the method MyEntities.textGetter()
when needed. If you use it only once, yes, you lose in terms of LOCs, but if you use it several times, you just win. Also, if you ever have a bug, you have to fix it only once and not find every usage to fix it everywhere.
然后,使用变得像在需要时使用方法MyEntities.textGetter()一样简单。如果你只使用它一次,是的,你就失去了LOC,但如果你多次使用它,你就赢了。此外,如果你有一个错误,你只需要修复一次,而不是找到每个用途来解决它到处都是。