【问题标题】:In java, how do I sort a generic class T on a Field variable sent to me在 java 中,如何对发送给我的 Field 变量的泛型类 T 进行排序
【发布时间】:2025-12-12 20:45:01
【问题描述】:
// this function can be called if the objects sent is Comparable (they have
// already chosen the field and how it compares)
public void mySort(Object [] obj) {
     Arrays.sort(obj, null);     // this sorts based on compareTo() 
                                 // method of comparable object
}

我的问题是如何更改以下函数以按字段字段对数组进行排序。我尝试了许多不同的实现方式,只是在下面放了代表我正在尝试做的代码。

// this function should be used to sort a generic array of T objects, to be
// compared on the Field field
public static <T> void mySort2(T [] obj, Field field) {
    Collections.sort(obj, new Comparator<T>(){
          public int compare(T obj1, T obj2)
          {
             return obj1.field.compareTo(obj2.field); // this does not work
                             //  since I need to the name of the field and
                             //  not a variable, however I do not know what
                             //  T will be when it is sent to me
          }
      });
}

【问题讨论】:

    标签: java sorting generics field


    【解决方案1】:

    您需要使用Field::get 反射性地访问该字段。之后,您需要转换为Comparable

    【讨论】:

    • 谢谢!经过一些试验和错误,我想我可以按照我在问题中的要求进行操作。
    【解决方案2】:

    您真的需要传递Field 实例并反思性地查找该字段吗?作为一种可能的替代方法(可能性能更高,具体取决于您的 JVM 实现),您可以传递 lambda 或方法引用来访问该字段:

    public static <T, U extends Comparable<? super U>> void mySort(
        T[] array,
        Function<T, U> func) {
      Arrays.sort(array, (a, b) -> func.apply(a).compareTo(func.apply(b));
    }
    

    你会这样称呼:

    Foo[] foos = ...
    mySort(foos, Foo::getMyField);    
    

    如果你被 Java 7 卡住了,你可以做同样的事情,但它有点冗长:

    public interface Function<I, O> {
      O apply(I input);
    }
    
    public static <T, U extends Comparable<? super U>> void mySort(
        T[] array,
        final Function<T, U> func) {
      Arrays.sort(array,
          new Comparator<T>() {
            @Override public int compareTo(T a, T b) {
              return func.apply(a).compareTo(func.apply(b));
            }
          });
    }
    

    你会这样称呼:

    Foo[] foos = ...
    mySort(foos,
        new Function<Foo, Integer>() {
          @Override public Integer apply(Foo foo) {
            return foo.getMyField();
          }
        });
    

    【讨论】:

    • 谢谢!只要我不需要反思性地查找字段,我肯定会使用这种类型的设置。不幸的是,我现在不确定这是否是一个硬性要求(等待其他人)。
    【解决方案3】:

    您问如何使用Field 进行操作,并给出了答案。如果出于某种原因这是一个严格的要求,那么我的回答是没有实际意义的,但如果不是,那么它是一种更好的方式,无需反思。

    首先,快速提一下,而不是T[] obj,它需要是List&lt;T&gt; obj

    现在进行其余的更改,

    1. 该方法的类型参数是&lt;T&gt;,我已将其更改为&lt;T, F extends Comparable&lt;F&gt;&gt;F 代表“字段”。 F 需要与自身具有可比性,这就是为什么它需要是 Comparable&lt;F&gt;
    2. 您需要一种从T 获取F 的方法。所以你给一个Function&lt;T, F&gt;,我将在下面给出一个例子。
    3. 比较方法需要返回getter.apply(obj1).compareTo(getter.apply(obj2))

    这是你的成品

    public static <T, F extends Comparable<F>> void mySort2(List<T> obj, final Function<T, F> getter) {
        Collections.sort(obj, new Comparator<T>() {
            public int compare(T obj1, T obj2) {
                return getter.apply(obj1).compareTo(getter.apply(obj2));
            }
        });
    }
    

    这是一个调用它按长度对字符串进行排序的示例。

    List<String> list = getSomeListOfStringsSomehow();
    mySort2(list, (String s) -> g.length());
    

    【讨论】:

    • 谢谢!这也是一个有趣的解决方案,如果使用 Fields 不是严格要求,我会考虑。