我经常遇到一个Java lambda表达式的问题,当我想对一个对象的任意属性或方法的一个流,但想要保持对象,而不是映射到该属性或方法。我开始创建容器,如讨论
here,但我开始做到足够让它变得恼人,并做了很多样板类。
我把这个Pairing类,它拥有两个类型的两个对象,允许你指定左,右,或两个对象的键控。我的问题是…有没有真正没有内置lambda流函数distinct()在一些关键供应商?这将真的让我感到惊讶。如果不是,这个类将可靠地实现该功能?
这里是如何被称为
BigDecimal totalShare = orders.stream().map(c -> Pairing.keyLeft(c.getCompany().getId(), c.getShare())).distinct().map(Pairing::getRightItem).reduce(BigDecimal.ZERO, (x,y) -> x.add(y));
这里是配对类
public final class Pairing {
private final X item1;
private final Y item2;
private final KeySetup keySetup;
private static enum KeySetup {LEFT,RIGHT,BOTH};
private Pairing(X item1, Y item2, KeySetup keySetup) {
this.item1 = item1;
this.item2 = item2;
this.keySetup = keySetup;
}
public X getLeftItem() {
return item1;
}
public Y getRightItem() {
return item2;
}
public static Pairing keyLeft(X item1, Y item2) {
return new Pairing(item1, item2, KeySetup.LEFT);
}
public static Pairing keyRight(X item1, Y item2) {
return new Pairing(item1, item2, KeySetup.RIGHT);
}
public static Pairing keyBoth(X item1, Y item2) {
return new Pairing(item1, item2, KeySetup.BOTH);
}
public static Pairing forItems(X item1, Y item2) {
return keyBoth(item1, item2);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
if (keySetup.equals(KeySetup.LEFT) || keySetup.equals(KeySetup.BOTH)) {
result = prime * result + ((item1 == null) ? 0 : item1.hashCode());
}
if (keySetup.equals(KeySetup.RIGHT) || keySetup.equals(KeySetup.BOTH)) {
result = prime * result + ((item2 == null) ? 0 : item2.hashCode());
}
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Pairing,?> other = (Pairing,?>) obj;
if (keySetup.equals(KeySetup.LEFT) || keySetup.equals(KeySetup.BOTH)) {
if (item1 == null) {
if (other.item1 != null)
return false;
} else if (!item1.equals(other.item1))
return false;
}
if (keySetup.equals(KeySetup.RIGHT) || keySetup.equals(KeySetup.BOTH)) {
if (item2 == null) {
if (other.item2 != null)
return false;
} else if (!item2.equals(other.item2))
return false;
}
return true;
}
}
更新:
测试Stuart的功能下面,它似乎工作很大。以下操作区分每个字符串的第一个字母。我想知道的唯一部分是ConcurrentHashMap如何只维护整个流的一个实例
public class DistinctByKey {
public static Predicate distinctByKey(Function super T,Object> keyExtractor) {
Map seen = new ConcurrentHashMap<>();
return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
}
public static void main(String[] args) {
final ImmutableList arpts = ImmutableList.of("ABQ","ALB","CHI","CUN","PHX","PUJ","BWI");
arpts.stream().filter(distinctByKey(f -> f.substring(0,1))).forEach(s -> System.out.println(s));
}
输出为…
ABQ
CHI
PHX
BWI