简体   繁体   English

在 Java 中对泛型列表进行排序?

[英]Sorting a list of Generics in Java?

I'm trying to implement a sorting for Generics in Java.我正在尝试在 Java 中实现对泛型的排序。 Here is the abstract class Function (T is my "key" in order to sort):这是抽象类函数(T 是我的“键”以便排序):

public abstract class Function<T extends Comparable<T>, S> {

    abstract public T compute(S o); 
}

Here is class Applier, whose method "apply" sorts the list according on the result of "compute":这是 Applier 类,它的方法“apply”根据“compute”的结果对列表进行排序:

import java.util.ArrayList;
import java.util.Iterator;

public class Applier<T extends Comparable<T>, S> {

    ArrayList<S> apply(ArrayList<S> input, Function<T, S> function) {
        ArrayList<T> output = new ArrayList<>(); 
        for(Iterator<S> it = input.iterator(); it.hasNext(); ){
            output.add(function.compute(it.next()));
        }
        T tmpTi, tmpTj; 
        S tmpSi, tmpSj; 
        for(int i=0; i<input.size(); i++) {
            for(int j=i+1; j<input.size(); j++) {
                if(output.get(i).compareTo(output.get(j))>0) {
                    tmpTi = output.get(i); 
                    tmpTj = output.get(j); 
                    output.remove(j); 
                    output.remove(i); 
                    output.add(i, tmpTi);
                    output.add(i, tmpTj);

                    tmpSi = input.get(i);
                    tmpSj = input.get(j);
                    input.remove(j);
                    input.remove(i);
                    input.add(i, tmpSj);
                    input.add(j, tmpSi);
                }
            }
        }
        return input; 
    }

}

My question is: is there a smarter way to do this sorting, maybe not with a bubblesort?我的问题是:有没有更聪明的方法来进行这种排序,也许不是冒泡排序? Here is also the main class:这里也是主类:

public static void main(String[] args) {
    Applier a = new Applier<>();
    StringLength strlen = new StringLength();

    ArrayList<String> array = new ArrayList<>();

    array.add("Hola");
    array.add("Man");
    array.add("randomstufff");
    array.add("Zerrone");
    array.add("Info3a");

    System.out.println("Order by length");
    System.out.print("before: ");
    System.out.println(array);
    a.apply(array, strlen); //works on original object
    System.out.print("After: ");
    System.out.println(array);

Note that there's an error in the way you swap elements in your Bubble Sort: When re-inserting the elements into output , you misplaced i and j .请注意,您在冒泡排序中交换元素的方式存在错误:将元素重新插入output ,您放错了ij Also, instead of removing and re-inserting the elements, just use set(index, element) to overwrite the previous entry.此外,不要删除和重新插入元素,只需使用set(index, element)覆盖前一个条目。

Also, instead of using two lists and keeping those lists in synch, better just use a Map .此外,与其使用两个列表并保持这些列表同步,不如使用Map

public static class Applier<T extends Comparable<T>, S> {
    ArrayList<S> apply(ArrayList<S> input, Function<T, S> function) {
        Map<S, T> compareBy = new HashMap<>();
        for (S s : input) {
            compareBy.put(s, function.compute(s));
        }
        for(int i=0; i<input.size(); i++) {
            for(int j=i+1; j<input.size(); j++) {
                if (compareBy.get(input.get(i)).compareTo(compareBy.get(input.get(j))) > 0) {
                    S tmpS = input.get(j);
                    input.set(j, input.get(i));
                    input.set(i, tmpS);
                }
            }
        }
        return input; 
    }
}

And of course, sorting is already implemented in Java.当然,排序已经在 J​​ava 中实现了。 So other than for learning how to code, you should always use the builtin functions.因此,除了学习如何编码之外,您应该始终使用内置函数。 In Java 8, it's just a single line:在 Java 8 中,它只是一行:

Collections.sort(array, Comparator.comparing(String::length));

Note, however, that Comparator.comparing will call the comparator function for each pairwise comparison (ie on the order of 2nlogn times for a decent sorting algorithm).但是请注意, Comparator.comparing将为每个成对比较调用比较器函数(即,对于合适的排序算法,大约为2nlogn次)。 If that function is computationally very expensive, you might want to cache it yourself, using a Map .如果该函数在计算上非常昂贵,您可能希望使用Map自己缓存它。

Map<String, Integer> compareBy = array.stream().collect(Collectors.toMap(s -> s, s -> s.length()));
Collections.sort(array, Comparator.comparing((String s) -> compareBy.get(s)));

Basically you want to sort an array based on some other array.基本上你想根据其他数组对数组进行排序。 You will be able to use Collections.sort if you introduce a wrapper object that contains both the values and the function results, and sort that one.如果您引入一个包含值和函数结果的包装器对象,并对其进行排序,您将能够使用Collections.sort

Here's a solution using Java 8 streaming API:这是使用 Java 8 流 API 的解决方案:

public class Applier<T extends Comparable<T>, S> {

    static class Wrapper<T extends Comparable<T>,S> implements Comparable<Wrapper<T,S>> {
        T key;
        S value;
        Wrapper(S s, Function<T, S> function) {
            this.key = function.compute(s);
            this.value = s;
        }
        public int compareTo(Wrapper<T,S> that) {
            return key.compareTo(that.key);
        }
    }
    ArrayList<S> apply(ArrayList<S> input, Function<T, S> function) {
        S[] sorted = (S[]) IntStream.range(0, input.size())
            .mapToObj(i -> new Wrapper<T,S>(input.get(i), function))
            .sorted()
            .map(b -> b.value).toArray();
        input.clear();
        input.addAll(Arrays.asList(sorted));
        return input;
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM