![](/img/trans.png)
[英]Java generics: Calling generic Method “…is not applicable for the arguments…”
[英]Generic method arguments - Java
我有兩個幾乎相同的方法,但我試圖避免代碼重復。
它們中的每一個都將一個唯一的對象作為參數,並從中找出最高的值。
這是一個例子:
public Integer getHighestIndexValue(List<ObjectA> list) {
int highestValue;
List<Integer> indexes = new ArrayList<Integer>();
for (ObjectA a: list) {
indexes.add(Integer.parseInt(a.getA()));
}
highestValue = Collections.max(indexes);
return highestValue;
}
要么:
public Integer getHighestIndexValue(List<ObjectB> list) {
int highestValue;
List<Integer> indexes = new ArrayList<Integer>();
for (ObjectB b: list) {
indexes.add(Integer.parseInt(b.getB()));
}
highestValue = Collections.max(indexes);
return highestValue;
}
如何使用通用參數組合這兩個?
我嘗試創建一個包含這兩個類的BaseClass
,並將其擴展到方法簽名中。 還是需要鑄造。
public <T extends BaseClass> Integer getHighestIndexValue(List<T> objectList) {
int highestValue;
List<Integer> indexes = new ArrayList<Integer>();
for (T objects: objectList) {
indexes.add(Integer.parseInt(objects.getAorB())); ------ this line needs casting
}
highestValue = Collections.max(indexes);
return highestValue;
}
我之前使用過Generics但尚未使用泛型參數。
有辦法解決這個問題嗎?
可以將getA
和getB
組合成單個接口方法嗎?
例如:
interface ProvidesIndex {
Integer getIndex();
}
現在,您只需調用getIndex
,您的方法簽名將是:
public Integer getHighestIndexValue(List<? extends ProvidesIndex> list)
作為旁注,如果您定義接口以擴展Comparable<ProvidesIndex>
即:
interface ProvidesIndex extends Comparable<ProvidesIndex>
然后,您可以直接在初始列表中使用Collections.max
:
List<ProvidesIndex> list = new ArrayList<ProvidesIndex>();
list.add(new ObjectA());
list.add(new ObjectB());
Integer max = Collections.max(list).getIndex();
拉曼補充說:
public Integer getHighestIndexValue(List<? extends CommonInterface> list) {
int highestValue;
List<Integer> indexes = new ArrayList<Integer>();
for (CommonInterface a: list) {
indexes.add(Integer.parseInt(a. getIndex()));
}
highestValue = Collections.max(indexes);
return highestValue;
}
Guava有一個優雅的解決方案:
//general purpose function to get A, can be used in transform(), etc
private static final Function<ObjectA, Integer> GET_A = new Function<>() {
@Override
public Integer apply(ObjectA a) {
return a.getA();
}
}
Integer highestIndex = Collections.max(Collections2.transform(list, GET_A));
或者,如果您需要具有最高索引的元素,
ObjectA highest = Ordering.natural().onResultOf(GET_A).max(list);
然后將其擴展到ObjectB
,你只需要實現一個GET_B
功能。
回到你的助手方法(現在基本上無關緊要了):
public <T> Integer getHighestIndex(List<? extends T> list, Function<? super T, Integer> indexPlucker) {
return Collections.max(Collections2.transform(list, indexPlucker));
}
您可以在一個Java命令中執行此操作。 這是Java 5和更緊湊的Java 8:
public static class ObjectA {
public String getA() { return "1"; /* test */ }
}
public static class ObjectB {
public String getB() { return "1"; /* test */ }
}
// Java 5+ versions
public static void sampleA7(List<ObjectA> list) {
int maxValue = Integer.parseInt(Collections.max(list, new Comparator<ObjectA>() {
@Override
public int compare(ObjectA a, ObjectA b) {
return Integer.parseInt(a.getA()) - Integer.parseInt(b.getA());
}
}).getA());
}
public static void sampleB7(List<ObjectB> list) {
int maxValue = Integer.parseInt(Collections.max(list, new Comparator<ObjectB>() {
@Override
public int compare(ObjectB a, ObjectB b) {
return Integer.parseInt(a.getB()) - Integer.parseInt(b.getB());
}
}).getB());
}
// Java 8+ versions
public static void sampleA8(List<ObjectA> list) {
Optional<Integer> maxValue = list.stream().map(a -> Integer.parseInt(a.getA())).max((a, b) -> a - b);
}
public static void sampleB8(List<ObjectB> list) {
Optional<Integer> maxValue = list.stream().map(a -> Integer.parseInt(a.getB())).max((a, b) -> a - b);
}
如果你想使這個代碼通用,那么使用整數的ArrayList來進行實際比較可能不是一個好主意。 如果其中一個對象是Long,大於你的最大整數怎么辦? 相反,您的對象必須以某種方式進行比較,因此您可以找到“最大值”(一組字符串的最大值是多少?)
所以我嘗試這樣的方法
import java.util.List;
public abstract class MathMax<E> {
public abstract boolean isGreaterThan(E x1, E x2);
public E getHighestIndexValue(List<E> list){
E highestValue = null;
for (E a: list) {
if (isGreaterThan(a,highestValue)){
highestValue = a;
}
}
return highestValue;
}
}
和
import java.util.ArrayList;
import java.util.List;
public class MathMaxA extends MathMax<ObjectA> {
@Override
public boolean isGreaterThan(ObjectA x1, ObjectA x2) {
// do your comparison here, careful with null values
return false;
}
public static void main(String[] args) {
MathMaxA m = new MathMaxA();
List<ObjectA> list = new ArrayList<ObjectA>();
System.out.println(m.getHighestIndexValue(list));
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.