Java 8-基于特定顺序的自定义排序

时间:2018-11-12 03:59:35

标签: java sorting java-8 comparator

我想根据用户状态对用户列表进行排序,但是顺序必须基于我设置的顺序。

我要设置列表的顺序

订单应为 1、0、5 。我们还应该记住也要订购用户名。

List<User> users = new ArrayList();
         users.add(new User("A", 1));
         users.add(new User("B", 5));
         users.add(new User("C", 0));
         users.add(new User("D", 1));
         users.add(new User("E", 5));
         users.add(new User("F", 0));

这是用户类别

public class User {
         private String username;
         private Integer status;
     }

应该看起来像这样

[
    {
      "username": "A",
      "status": 1
    },
    {
       "username": "D",
       "status": 1
    },
    {
       "username": "C",
       "status": 0
    },
    {
       "username": "F",
       "status": 0
    },
    {
       "username": "B",
       "status": 5
    },
    {
       "username": "E",
       "status": 5
    }
]

我不确定是否可以使用 Comparator.comparing ,因为这既不是升序也不是降序。

5 个答案:

答案 0 :(得分:9)

一种方法可能是保存所需顺序的列表,并根据其索引对用户进行排序:

final List<Integer> order = Arrays.asList(1, 0, 5);
users.sort(
    Comparator.comparing((User u) -> order.indexOf(u.getStatus()))
              .thenComparing(User::getUsername));

请注意,尽管这种方法对于少量状态(如您当前拥有的状态)应该是合理的,但是如果存在大量状态,并且每个状态都需要执行O(n)搜索,则可能会减慢排序速度时间。一种性能更好的方法(虽然可以说不那么时尚)将是使用地图:

final Map<Integer, Integer> order = new HashMap<>();
order.put(1, 0);
order.put(0, 1);
order.put(5 ,2);
users.sort(Comparator.comparing((User u) -> order.get(u.getStatus()))
                     .thenComparing(User::getUsername));

答案 1 :(得分:6)

如果您不介意在项目中使用番石榴,则可以使用import ... from ...

Ordering.explicit

如果您还想按名称排序,请添加users.sort(Ordering.explicit(1, 0, 5).onResultOf(User::getStatus));

thenComparing

答案 2 :(得分:1)

假设105将是status的唯一值,AJNeufeld在their comment中提出了一个很好的观点;他们表示您可以使用方程式将每个值映射为升序。在这种情况下,等式为(x - 1)^2,其中xstatus的值:

users.sort(Comparator.comparingDouble(user -> Math.pow(user.getStatus() - 1, 2)));

如果在调用上述代码段后要打印user的内容,则会得到:

  

[用户[用户名= A,状态= 1],用户[用户名= D,状态= 1],用户[用户名= C,状态= 0],用户[用户名= F,状态= 0],用户[用户名= B,状态= 5],用户[用户名= E,状态= 5]]

答案 3 :(得分:0)

您可以尝试逐步进行此操作

import csv, json,os

x = """[
        ....   I have data here
    ]"""

img_data = json.loads(x)

#Uname is going to hold the current user name
Uname=os.getlogin()

# I want to use %USERNAME% here instead of each time changing the qid for different users
##Ensure this folder exists
outputFile = open("C:/Users/"+Uname+"/Desktop/JSON/imageData1.csv", "w")

csvwriter = csv.writer(outputFile)

csvwriter.writerow( ["fileName", "path", "annotatedImagePath", "resultFilePath", "numberOfDetectedObject", "numberOfQualifiedObject", "analysisDate", "hasFailed"] )

for row in img_data:
     csvwriter.writerow( [row["fileName"], row["path"], row["annotatedImagePath"], row["resultFilePath"], row["numberOfDetectedObject"], row["numberOfQualifiedObject"], row["analysisDate"], row["hasFailed"] ] )

outputFile.close()

答案 4 :(得分:0)

如前所述,您需要自定义排序,这意味着您需要在HashMap << strong> Status,Rank >>或一种简单的方法中定义排序的某个地方,再添加一个属性,例如 Integer rank; ,然后您可以根据状态属性的排序来定义排名,例如says users.add(new User(“ A”,1,0));在这里,状态1是最排序的,其等级= 0。然后,您可以在等级属性上使用 Comparator

例如:

public class User {
    public String username;
    public Integer status;
    public Integer rank;

    public User(String username, Integer status, Integer rank) 
    { 
        this.username = username; 
        this.status = status; 
        this.rank = rank;
    } 
}

比较器类:

class SortByRank implements Comparator<User> 
{ 
    // Used for sorting in ascending order of 
    // rank number 
    public int compare(User a, User b) 
    { 
        return a.rank - b.rank; 
    } 
} 

主类:

class Main 
{ 
    public static void main (String[] args) 
    { 
         List<User> users = new ArrayList();
         users.add(new User("A", 1, 0));
         users.add(new User("B", 5, 2));
         users.add(new User("C", 0, 1));
         users.add(new User("D", 1, 0));
         users.add(new User("E", 5, 2));
         users.add(new User("F", 0, 1));

        System.out.println("Unsorted"); 
        for (int i=0; i<users.size(); i++) 
            System.out.print(users.get(i).username); 

        Collections.sort(users, new SortByRank()); 

        System.out.println("\nSorted by Rank"); 
        for (int i=0; i<users.size(); i++) 
            System.out.print(users.get(i).username); 
    } 
}