Java按名称排序对象列表,但一个对象应始终位于顶部

时间:2018-01-26 15:57:55

标签: java sorting java-8 comparator

class Manager
{
    private int id;
    private String name;

    public Manager(int id, String name)
    {
      this.id = id;
      this.name = name;
    }

    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public int getId() { return id; }
    public void setId(int id) { this.id = id; }
}

List<Manager> names = new ArrayList<>();
names.add(new Manager(1, "Robert"));
names.add(new Manager(2, "Paul"));
names.add(new Manager(3, "None"));
names.add(new Manager(4, "Nancy"));
names.add(new Manager(4, "Nancy"));

names.stream().sorted(
                Comparator.comparing(n->n.getName())).collect(Collectors.toList());


List<String> names = new List<String>();
names.add("Robert");
names.add("Paul");
names.add("None");
names.add("Nancy");
names.add("Nancy");


names.stream().sorted().collect(Collectors.toList());

我需要在Java 8中对字符串列表进行排序,我可以使用下面的逻辑轻松完成,但我想在下面的列表中始终显示None。结果必须如此。我需要获取List of Managers对象的排序顺序

None
Jhon
Nancy
Paul

我的代码:

List<String> names = new List<String>();
names.add("Robert");
names.add("Paul");
names.add("None");
names.add("Nancy");
names.add("Jhon");


names.stream().sorted().collect(Collectors.toList());

字符串必须始终位于第一位。

7 个答案:

答案 0 :(得分:5)

您可以使用

List<Manager> sorted = names.stream()
    .sorted(Comparator.comparing(Manager::getName,
              Comparator.comparing((String s) -> !s.equals("None"))
                        .thenComparing(Comparator.naturalOrder())))
    .collect(Collectors.toList());

分类到新列表或使用

names.sort(Comparator.comparing(Manager::getName,
              Comparator.comparing((String s) -> !s.equals("None"))
                        .thenComparing(Comparator.naturalOrder())));

进行就地排序,这可以使用像ArrayList这样的可变列表。

答案 1 :(得分:3)

您可以将比较器对象传递给定义条件的sorted中间方法,如下所示:

List<String> resultSet = 
         names.stream()
              .sorted((e, a) -> "None".equals(e) ? -1:
                              "None".equals(a) ? 1 : e.compareTo(a))
              .collect(Collectors.toList());

答案 2 :(得分:2)

一种方法是过滤掉"None",并将其预先挂起到排序列表中:

List<String> ordered = Stream.concat(
    names.stream().filter(s -> s.equals("None"))
,   names.stream().filter(s -> !s.equals("None")).sorted()
).collect(Collectors.toList());

Demo.

答案 3 :(得分:0)

使用sortedpartitioningBy

    Map<Boolean, List<String>> partition = names
            .stream()
            .sorted()
            .collect(Collectors.partitioningBy("None"::equals));
    System.out.println(partition);

    List<String> noneFirst = new ArrayList<>(partition.get(true));
    noneFirst.addAll(partition.get(false));
    System.out.println(noneFirst);

输出

[None, Jhon, Nancy, Paul, Robert]

答案 4 :(得分:0)

List<String> sorted = names.stream()
                .sorted((o1, o2) -> o1 == null ?
                        -1 :
                        o2 == null ?
                                1 :
                                o1.equals("None") ?
                                        -1 :
                                        o2.equals("None") ?
                                                1 :
                                                o1.compareTo(o2))
                .collect(Collectors.toList());

答案 5 :(得分:0)

这是我的贡献:尝试使其格式化/看起来尽可能好。 请注意,这将失败。

 List<String> unsorted = ... what-ever ...;
 // ... 
 List<String> sorted = unsorted.stream()
    .filter(Objects::nonNull) // optional: get rid of nulls before an exception is thrown bellow.
    .sorted((a, b) -> Objects.equals(a, b) ? 0 
                  : "None".equals(a) ? -1
                  : "None".equals(b) ? 1 
                  : a.compareTo(b))
    .distinct()  // optional: if you want to get rid of repeats.
    .collect(Collectors.toList());

答案 6 :(得分:-1)

检查出来

   names.stream()
                        .sorted((o1, o2) ->
                                {
                                    if("None".equals(o1.getName()) && "None".equals(o2.getName())) return 0;
                                    return "None".equals(o1.getName()) ? -1:
                                            "None".equals(o2.getName()) ? 1 : o1.getName().compareTo(o2.getName());
                                }
                        ).collect(Collectors.toList());