java - 使用 Java 8 流对多个变量列表进行排序

标签 java sorting java-8 java-stream

我有一个包含多个变量的对象列表。我想根据运行时决定的顺序对这个列表进行排序。我想出了以下看起来效率不高的代码。例如,如果变量不是 3 而是 10 或 30 会怎样?谁能建议更好的方法来做到这一点?

import java.util.List;
import java.util.function.Function;
import static java.util.Comparator.*;
import static java.util.stream.Collectors.*;

public class SortXYZ {
    double x;
    String y;
    double z;

public double getX() {return x; }
public String getY() {return y; }
public double getZ() {return z; }

 public static void main(String[] arg)   {
    Function<SortXYZ, Double> f1 = SortXYZ::getX;
    Function<SortXYZ, String> f2 = SortXYZ::getY;
    Function<SortXYZ, Double> f3 = SortXYZ::getZ;
    //could have f4, f5 etc.

    List<SortXYZ> list = getList(); //get a list of SortXYZ objects 

    String sortSeq = arg[0];
    if (sortSeq.equals("XYZ")) {
        list = list.stream().sorted(comparing(f1).thenComparing(f2).thenComparing(f3)).collect(toList());
    } else if (sortSeq.equals("XZY")) {
        list = list.stream().sorted(comparing(f1).thenComparing(f3).thenComparing(f2)).collect(toList());
    } else if (sortSeq.equals("YXZ")) {
        list = list.stream().sorted(comparing(f2).thenComparing(f1).thenComparing(f3)).collect(toList());
    } else if (sortSeq.equals("YZX")) {
        list = list.stream().sorted(comparing(f2).thenComparing(f3).thenComparing(f1)).collect(toList());
    } else if (sortSeq.equals("ZXY")) {
        list = list.stream().sorted(comparing(f3).thenComparing(f1).thenComparing(f2)).collect(toList());
    } else if (sortSeq.equals("ZYX")) {
        list = list.stream().sorted(comparing(f3).thenComparing(f2).thenComparing(f1)).collect(toList());
    } 


}
 }

最佳答案

我暂时忽略了 Comparator 中的原始类型。稍后将尝试提高类型安全性。


您可以创建接受比较器模式的方法,并基于它创建一个比较器。为了让生活更轻松,您还可以将 getter 引用(f1 f2 ..)存储在 map 中,例如

@SuppressWarnings("rawtypes") 
static Map<String, Function<SortXYZ, Comparable>> gettersMap = new HashMap<>();
static {
    gettersMap.put("x", SortXYZ::getX);
    gettersMap.put("y", SortXYZ::getY);
    gettersMap.put("z", SortXYZ::getZ);
}

所以创建比较器的方法看起来像

@SuppressWarnings("unchecked")
static Comparator<SortXYZ> getComparator(String order){
    String[] keys = order.toLowerCase().split("");
    Comparator<SortXYZ> result = Comparator.comparing(gettersMap.get(keys[0]));
    for (int i = 1; i<keys.length; i++){
        result = result.thenComparing(gettersMap.get(keys[i]));
    }
    return result;
}

顺便说一句:在你的代码中:

list = list.stream().sorted(Comparator.comparing(f3).thenComparing(f2).thenComparing(f1)).collect(toList());

您正在对列表进行排序,并将元素写入新列表,然后再次将其分配给 list 引用。如果你想对当前列表中的元素进行排序,你可以简单地使用

list.sort(yourComparator);

因此您的代码现在看起来更像:

List<SortXYZ> list = getList(); //get a list of SortXYZ objects 

String sortSeq = arg[0];
list.sort(getComparator(sortSeq));

关于java - 使用 Java 8 流对多个变量列表进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30624612/

相关文章:

java - 如何在 Android 应用程序中运行静态内部类

javascript - 使用 JavaScript 将纯文本列表转换为 HTML 列表

java - 列表Java Spring中的分页

if-statement - Java8 : Implement multiple conditional statements with stream API

spring - 无法仅在 Spring Data Neo4j 中将事务标记为回滚

java - 当 API 说接口(interface)的方法返回某些内容时,它是什么意思?

java - 如何在java中检查POST端点/url的状态

java - List<Integer> 作为 JRBeanCollectionDataSource 到子报表中,如何获取报表上显示的整数值?

java - Android 媒体播放器 OncompletionListener 播放下一首歌曲但不播放第二首歌曲

c - 使用其他数组对数组进行排序