[英]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
,您放错了i
和j
。 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.当然,排序已经在 Java 中实现了。 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.