我是 Java 泛型的新手,我目前一直在确定列表中 Pair 对象(apache 的)的类型。
我有两个类 A 和 B,它们都有一个方法执行完全相同的操作(代码重复)。
方法是这样的:
private List<Pair<String, A>> deduplicateItems(List<Pair<String, A>> list) {
List<Pair<String, A>> deduplicatedItems = new ArrayList<>();
list.forEach(item-> {
//do something
deduplicatedItems.add(item);
});
}
完全相同的方法在B类中(Value in Pair的类型是B)。
我想创建一个通用的抽象类来处理这个操作。
我到目前为止:
public abstract class AbstractHelper<V> {
private List<Pair<String, V>> deduplicateItems(List<Pair<String, V>> list) {
List<Pair<String, V>> deduplicatedItems = new ArrayList<>();
//problem here determining the type of class for this generic
});
}
}
我想确定 V 的类型并将其转换为能够访问 get() 方法。
使用
list.get(0) instanceof A
是正确的做法吗?我觉得这可能太天真了,但我在这里可能是错的。
使方法通用:
private <T> List<Pair<String, T>> deduplicateItems(List<Pair<String, T>> list) {
List<Pair<String, T>> deduplicatedItems = new ArrayList<>();
list.forEach(item-> {
//do something
deduplicatedItems.add(item);
});
return deduplicatedItems;
}
如果 A 和 B 都实现了相同的接口或扩展了一个共同的父类,并且您希望“做某事”以这种方式与元素交互,请在 T 上设置一个界限:
private <T extends MyCommonType> List<Pair<String, T>> deduplicateItems(List<Pair<String, T>> list) {
你不应该检查类型。你绝对不应该写像
if (element instanceof A) { } else if (element instanceof B) { } else if
之类的东西
问题是你的方法不知道如何检查类型 V 的两个实例是否相等。由于您的方法没有该信息,您应该强制调用者提供该信息:
private List<Pair<String, V>> deduplicateItems(
List<Pair<String, V>> list,
BiPredicate<? super V, ? super V> equalityChecker) {
List<Pair<String, V>> deduplicatedItems = new ArrayList<>();
List<V> existingValues = new ArrayList<>();
for (Pair<String, V>> pair : list) {
V value = pair.getValue();
if (existingValues.stream().noneMatch(
v -> equalityChecker.test(v, value)) {
existingValues.add(value);
deduplicatedItems.add(pair);
}
}
return deduplicatedItems;
}
BiPredicate 是一个测试两个值并返回基于它们的布尔值的接口。一个示例用法可能是:
List<Pair<String, String>> numbers = new ArrayList<>();
numbers.add(Pair.of("1", "ONE"));
numbers.add(Pair.of("1", "one"));
numbers.add(Pair.of("2", "TWO"));
numbers.add(Pair.of("2", "two"));
numbers.add(Pair.of("3", "THREE"));
numbers.add(Pair.of("3", "three"));
List<Pair<String, String>> uniqueNumbers =
deduplicateItems(numbers, String::equalsIgnoreCase);
如果 V 将代表的每个类都定义了可靠的 equals 方法,则不需要第二个参数,并且可以使用 Set 来更有效地检查重复值:
private List<Pair<String, V>> deduplicateItems(List<Pair<String, V>> list) {
List<Pair<String, V>> deduplicatedItems = new ArrayList<>();
Set<V> existingValues = new HashSet<>();
for (Pair<String, V>> pair : list) {
if (existingValues.add(pair.getValue())) {
deduplicatedItems.add(pair);
}
}
return deduplicatedItems;
}
上面的工作因为Set.add方法保证了:
退货:
如果这个集合还没有包含指定的元素true
当然,你也可以同时定义上面的两个deduplicateItems方法,让调用代码决定在给定的情况下哪个合适。