在通用 ArrayList 中查找最小值

Finding smallest value in generic ArrayList

我不断收到一条消息,告诉我运算符 < 对于类型 T,T 是未定义的。这发生在

左右
if(index<lowest)

我将如何修改我的程序,以便我可以使用通用方法获取数组列表的最小值和最大值?

package p07;

import java.util.ArrayList;

public class MyList<T extends Number> {
    private ArrayList<T> l;

    public MyList(ArrayList<T> l) {
        this.l=l;
    }
    public void add(T x) {
        l.add(x);
    }
    public static <T> void smallest(ArrayList<T> l) {
        T lowest=l.get(0);
        for(T index:l) {
            if(index<lowest) { 

            }
        }   
    }
}

编译器是对的:运算符<只适用于原始数值类型。引用 JLS 的 section 15.20.1:

The type of each of the operands of a numerical comparison operator must be a type that is convertible (§5.1.8) to a primitive numeric type, or a compile-time error occurs.

因此,它没有为对象定义,甚至没有为数字定义,因为它们不能被拆箱为原始类型:JLS 的 section 5.1.8

A type is said to be convertible to a numeric type if it is a numeric type (§4.2), or it is a reference type that may be converted to a numeric type by unboxing conversion.

你需要的是使用一个Comparator or make your objects ComparableComparator负责比较两个相同类型的对象。由于这里的对象是数字,而不是Comparable,你需要使用自定义的Comparator,像这样:

Comparator<Number> myComparator = new Comparator<Number>() {
    @Override
    public int compareTo(Number n1, Number n2) {
        // implement logic here.
        // Return -1 if n1 < n2, 0 if n1 = n2, 1 if n1 > n2
    }
};

然后你可以像这样使用这个比较器:

public static <T extends Number> T smallest(List<T> l) {
    T lowest = l.get(0);
    for (T index : l) {
        if (myComparator.compareTo(index, lowest) < 0) { 
            index = lowest;
        }
    }
    return lowest;
}

(请注意,我将 T extends Number 添加到方法的类型中 - 那是因为该方法是静态的,所以它实际上声明了另一种类型 T 而 class是)。

这里有几处错误,但让我们从容易实现的语法水果开始。

算术运算符适用于原始值,而T非常类似于Object,因此您将无法使用它们这里。

您的语法的另一个细微差别是您 T 的静态函数 不同T 绑定到您的 class.

您可以通过自己添加绑定来解决这个问题...

public static <T extends Number> void smallest(ArrayList<T> l)

...但这让我想问,为什么你希望这个方法完全是静态的?

您正在使用参数 l 隐藏字段 l 的名称,因此虽然您可能认为这对提供的实例 l 有效,但它不会,因为方法本身已声明 static,如果不是,您仍然会隐藏字段的名称。

您应该做的是从该方法中删除 static,并从函数中删除参数。

public void smallest() {}

但是现在,您遇到了一个问题,您实际上 return 不知道最小值是多少。你应该 return 它而不是什么都没有:

public T smallest() {}

如果您能够排序,从数组中取出最后一个值是很简单的。您只需要确保所有元素都是 Comparable 以便可以对它们进行排序,以及您最关心的值 - 例如 IntegerDoubleFloat , Long - 是.

public class MyList<T extends Number & Comparable<T>> {}

如果你可以排序,那么得到最小的就是直截了当:

public T smallest() {
    // Don't mutate the order of the original array.
    ArrayList<T> listCopy = new ArrayList<>(l);
    Collections.sort(listCopy);
    return listCopy.get(0);
}

通过这种方法获得最高我留作 reader 的练习。