Java 番石榴链序
我对番石榴有点陌生,这是我的风格。我肯定是在挖掘它,但有一件事我经常被绊倒,那就是链式方法的顺序。我发现这个问题最多的地方是在使用复合Java 番石榴链序,java,guava,method-chaining,Java,Guava,Method Chaining,我对番石榴有点陌生,这是我的风格。我肯定是在挖掘它,但有一件事我经常被绊倒,那就是链式方法的顺序。我发现这个问题最多的地方是在使用复合排序时。我必须不断地问自己这样的问题: natural去哪里了 nullFirst(或last)在哪里 哪个nullsFirst做什么?(在下面的示例中,一个代表主机,一个代表姓氏,一个代表名字?) 这是一个我刚刚研究的例子。它看起来很笨重,我只是不确定我是否把它放在一起了。我有一些JUnits来测试它,看起来还可以,但总有一些奇怪的边界情况 Ordering
排序时。我必须不断地问自己这样的问题:
natural
去哪里了
nullFirst
(或last)在哪里
- 哪个
nullsFirst
做什么?(在下面的示例中,一个代表主机,一个代表姓氏,一个代表名字?)
这是一个我刚刚研究的例子。它看起来很笨重,我只是不确定我是否把它放在一起了。我有一些JUnits来测试它,看起来还可以,但总有一些奇怪的边界情况
Ordering<Host> lastNameThenFirstNameOrdering = Ordering.natural().nullsFirst().onResultOf(new Function<Host, String>() {
public String apply(Host host) {
return host.getLastName();
}}).compound(Ordering.natural().nullsFirst().onResultOf(new Function<Host, String>() {
public String apply(Host host) {
return host.getFirstName();
}})).nullsFirst();
Ordering lastNameThenFirstNameOrdering=Ordering.natural().nullsFirst().onResultOf(新函数(){
公共字符串应用(主机){
返回host.getLastName();
}}).component(Ordering.natural().nullsFirst().onResultOf(新函数()){
公共字符串应用(主机){
返回host.getFirstName();
}})).nullsFirst();
至于一个实际的问题:这些事情是如何执行的,是否有一个明确的规则?这似乎是倒数第二,但我很难说出这一点
编辑:只是想指出我试图替换的又大又丑的代码:
Ordering<Host> ordering2 = new Ordering<Host>() {
public int compare(Host host1, Host host2) {
if (host1 == null || host2 == null) {
return host1 == host2 ? 0 : ((host1 == null) ? -1 : 1);
}
if(host1.getLastName() != null || host2.getLastName() != null){
if (host1.getLastName() == null) {
return -1;
} else if (host2.getLastName() == null) {
return 1;
}
if (host1.getLastName().compareTo(host2.getLastName()) != 0) {
return host1.getLastName().compareTo(host2.getLastName());
}
}
if (host1.getFirstName() == null) {
return -1;
} else if (host2.getFirstName() == null) {
return 1;
}
return host1.getFirstName().compareTo(host2.getFirstName());
}};
ordering2=新订单(){
公共整数比较(主机主机1、主机2){
if(host1==null | | host2==null){
返回host1==host2?0:((host1==null)?-1:1);
}
if(host1.getLastName()!=null | | host2.getLastName()!=null){
if(host1.getLastName()==null){
返回-1;
}else if(host2.getLastName()==null){
返回1;
}
如果(host1.getLastName().compareTo(host2.getLastName())!=0){
返回host1.getLastName().compareTo(host2.getLastName());
}
}
if(host1.getFirstName()==null){
返回-1;
}else if(host2.getFirstName()==null){
返回1;
}
返回host1.getFirstName().compareTo(host2.getFirstName());
}};
我认为你所做的是正确的,但非常丑陋。请尝试以下方法以提高可读性:
使用枚举
将函数移动到实现函数的枚举中
。每个枚举项都可以提供自己的实现
enum HostFunctions implements Function<Host, String>{
GETFIRSTNAME{
@Override
public String apply(final Host host){
return host.getFirstName();
}
},
GETLASTNAME{
@Override
public String apply(final Host host){
return host.getLastName();
}
}
}
enum主机函数实现函数{
GETFIRSTNAME{
@凌驾
公共字符串应用(最终主机){
返回host.getFirstName();
}
},
GETLASTNAME{
@凌驾
公共字符串应用(最终主机){
返回host.getLastName();
}
}
}
缩进代码
现在引用那些枚举函数并正确缩进代码。这就是它的样子:
final Ordering<Host> orderingByLastAndFirstName =
Ordering
.natural()
.nullsFirst()
.onResultOf(HostFunctions.GETLASTNAME)
.compound(
Ordering
.natural()
.nullsFirst()
.onResultOf(HostFunctions.GETFIRSTNAME))
.nullsFirst();
最终订单OrderingByStandfirstName=
订购
.natural()
.nullsFirst()
.onResultOf(HostFunctions.GETLASTNAME)
.化合物(
订购
.natural()
.nullsFirst()
.onResultOf(HostFunctions.GETFIRSTNAME))
.nullsFirst();
我想说这让一切都更容易理解
IDE配置
关于正确的缩进(至少如果您使用Eclipse),请参见以下问题:
枚举作为函数
关于枚举:这称为枚举单例模式。番石榴的家伙们在他们的代码库中使用它。阅读相关内容,或在第3项中阅读。虽然这两个源都谈到了单项枚举,但这里的方法几乎相同。每个链接调用都是将以前的顺序“包装”到新的顺序中,因此您是对的,执行顺序可以被认为是“向后的”
我编写并审阅了Ordering类,但我仍然必须经常停下来仔细研究nullsFirst()和onResultOf()与reverse()的正确交错 假设您必须能够处理null
hosts、first name和last name,那么我更愿意这样做。在我看来,非null
名字和姓氏应该是Host
类的要求。通常,您应该避免允许集合包含null
对象
Ordering<Host> lastNameFirstNameOrdering = new Ordering<Host>() {
@Override public int compare(Host left, Host right) {
return ComparisonChain.start()
.compare(left.getLastName(), right.getLastName(), Ordering.natural().nullsFirst())
.compare(left.getFirstName(), right.getFirstName(), Ordering.natural().nullsFirst())
.result();
}
}.nullsFirst();
排序lastNameFirstNameOrdering=新排序(){
@覆盖公共整数比较(主机左侧、主机右侧){
返回ComparisonChain.start()
.compare(left.getLastName()、right.getLastName()、Ordering.natural().nullsFirst())
.compare(左.getFirstName(),右.getFirstName(),Ordering.natural().nullsFirst())
.result();
}
}.nullsFirst();
或者,我会采取一种类似于肖恩的方法,但为了可读性,我会将内容分解
Ordering<Host> lastNameOrder = Ordering.natural().nullsFirst()
.onResultOf(Host.LAST_NAME);
Ordering<Host> firstNameOrder = Ordering.natural().nullsFirst()
.onResultOf(Host.FIRST_NAME);
Ordering<Host> orderingByLastAndFirstName =
lastNameOrder.compound(firstNameOrder).nullsFirst();
排序lastNameOrder=Ordering.natural().nullsFirst()
.onResultOf(主机名);
Ordering firstNameOrder=Ordering.natural().nullsFirst()
.onResultOf(主机名);
订购OrderingByStandFirstName=
复合(firstNameOrder).nullsFirst();
请记住,您还可以将这些单独的排序设置为类的静态最终字段,这样您就可以在排序时方便地在任何地方使用它们,比如
Host.LAST\u NAME\u ORDER
,或者这太乱了,不值得吗?也许我应该把这两个子顺序分开,以一种更具表现力的方式组合起来。.方法链的设计是为了在某些情况下使代码更具可读性。在这种情况下,它损害了您的代码、该代码的未来维护者以及阅读您的问题的所有人的眼睛。您是否建议我应该通过自定义实现来实现这一点?我不确定这是否会让人更眼花缭乱:(添加到帖子中)感谢大家对enum单曲的关注