我想撰寫一個函式,為每個串列元素添加一個常量。該串列可以是 Doubles 或 Integers 或類似的東西。我寫的:
static <T> List<T> forEachIndexChange(List<T> list,
Function<Integer, T> cb) {
for (int i = 0; i < list.size(); i) {
list.set(i, cb.apply(i));
}
return list;
}
static <T extends Number> List divide(List<T> list, int val) {
return forEachIndexChange(list, i -> list.get(i) / val);
}
然后編譯器溢位我無法呼叫/類Number:
error: bad operand types for binary operator '/'
return forEachIndexChange(list, i -> list.get(i) / val);
^
first type: T
second type: int
where T is a type-variable:
T extends Number declared in method <T>divide(List<T>,int,T)
太好了,然后讓我根據型別多載:
static <T extends Number> List divide(List<T> list, int val, T type) {
if (type instanceof Double) {
return forEachIndexChange(list, i -> list.get(i).doubleValue() / val);
}
return null;
}
static <T extends Number> List divide(List<T> list, int val) {
if (list.size() == 0) return list;
return divide(list, val, list.get(0));
}
但這會溢位一條我不明白的錯誤訊息:
error: incompatible types: inference variable T#1 has incompatible bounds
return forEachIndexChange(list, i -> list.get(i).doubleValue() / val);
^
equality constraints: T#2
lower bounds: Double
where T#1,T#2 are type-variables:
T#1 extends Object declared in method <T#1>forEachIndexChange(List<T#1>,Function<Integer,T#1>)
T#2 extends Number declared in method <T#2>divide(List<T#2>,int,T#2)
單獨多載多個T也不起作用,因為據我了解,List它會洗掉有關T何時多載函式的資訊。看起來我基本上被迫為每種型別撰寫一個單獨的函式名。
如何撰寫通用演算法來置換 Java 中的每個串列元素?有沒有更好的方法來解決 Java 中的此類問題?
uj5u.com熱心網友回復:
首先,當流中已經有 map() 函式時,為什么要撰寫自定義函式來更改集合?
我不確定的第二件事是,您為什么要使用未知數字型別串列。它允許您在串列中有不同的型別,并且您仍然希望除以整數,例如在處理位元組時可能會出現問題..
不過,我會做這樣的事情:
private static <T extends Number> List<T> divide(List<T> orig, int divisor) {
return orig.stream()
.map(it -> divide(it, divisor))
.toList();
}
private static <T extends Number> T divide(T num, int divisor) {
if (num instanceof Double) return (T) Double.valueOf(num.doubleValue() / divisor);
if (num instanceof Float) return (T) Float.valueOf(num.floatValue() / divisor);
if (num instanceof Long) return (T) Long.valueOf(num.longValue() / divisor);
if (num instanceof Integer) return (T) Integer.valueOf(num.intValue() / divisor);
if (num instanceof Byte) return (T) Byte.valueOf((byte) (num.byteValue() / divisor)); // this might be problem if divisor is greater than 127
throw new IllegalStateException("Cannot divide class of " num.getClass());
}
請注意,原始集合不受影響。如果需要更改原始集合(盡管我認為這不是好習慣),您可以這樣做:
private static <T extends Number> void divide(List<T> orig, int divisor) {
for (var i = 0; i < orig.size(); i ) {
orig.set(i, divide(orig.get(i), divisor));
}
}
uj5u.com熱心網友回復:
如果您對手動檢查型別感到滿意,并假設您只傳遞包含單一型別數字的串列(無論如何,具有不同型別數字的串列非常罕見),您可以這樣做:
static <T extends Number> List<T> divide(List<T> list, int val) {
if (list.isEmpty()) return list;
if (list.get(0) instanceof Double) {
return forEachIndexChange(list, i -> (T)(Object)(list.get(i).doubleValue() / val));
}
if (list.get(0) instanceof Integer) {
return forEachIndexChange(list, i -> (T)(Object)(list.get(i).intValue() / val));
}
// other types you want to support...
throw new UnsupportedOperationException();
}
請注意,這會產生未經檢查的強制轉換警告。這只是意味著 Java 無法檢查強制轉換T在運行時是否安全。但這很好,因為我們已經使用前一行的 if 陳述句檢查了自己。例如,在第一個 if 陳述句中,我們檢查了串列確實包含Double,(Object)(list.get(i).doubleValue() / val)產生了 a Double,所以強制轉換絕對是安全的。
uj5u.com熱心網友回復:
你forEachIndexChange()的足夠通用,應該按原樣使用。
public static void main(String[] args) {
List<Integer> integers = Arrays.asList(9, 6, 2, 3);
System.out.println(forEachIndexChange(integers, i -> integers.get(i) / 2));
List<Double> doubles = Arrays.asList(9.0, 6.0, 2.0, 3.0);
System.out.println(forEachIndexChange(doubles, i -> doubles.get(i) / 2));
}
輸出:
[4, 3, 1, 1]
[4.5, 3.0, 1.0, 1.5]
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/528367.html
標籤:爪哇模板仿制药数组列表
下一篇:可識別為泛型和func引數
