2017-03-03 100 views
0

我正在使用Java-8 lambda对列表进行排序。如何在JAVA8 lambda中使用条件进行排序

这里是后排序

[(t2, tester2), (t1, tester1), (t3, tester3), (t4, tester4)] 

我想要得到的结果如上

String specialId = 't2' 

List<Test> list = new ArrayList<>(); 

Test test1 = new Test(); 
test1.setId = "t1" 
test1.setName = "tester1" 
list.add(test1) 

Test test2 = new Test(); 
test2.setId = "t4" 
test2.setName = "tester4" 
list.add(test2) 

Test test3 = new Test(); 
test3.setId = "t3" 
test3.setName = "tester3" 
list.add(test3) 

Test test4 = new Test(); 
test4.setId = "t2" 
test4.setName = "tester2" 
list.add(test4) 

Stream<Test> s1 = list.stream.filter(t -> t.getId.equals(specialId)); 
Stream<Test> s2 = list.stream.filter(t -> !t.getId.equals(specialId)) 
        .sorted(Comparator.comparing(Test::getName)); 

Stream<Test> s = Stream.concat(s1, s2); 

List<Test> result = s.collect(Collectors.toList()); 

我得到预期的结果

[(t1, tester1), (t4, tester4), (t3, tester3), (t2, tester2)] 

名单。但我只想使用一次流。 我如何分类?

+0

是项T2首先,因为它是唯一的例外,还是有更多的一般方法的项目先去哪个? – wumpz

+0

在这种情况下,没有流可能会更简单:'List result = new ArrayList <>(list); result.sort(...);'你可以在[...]中使用[kennytm's answer](http://stackoverflow.com/a/42575546/2711488)的比较器。 – Holger

回答

1

我想你很清楚流是懒惰评估。

Stream<Test> s1 = list.stream.filter(t -> t.getId.equals(specialId)); 

你可以拿出Predicate,因为你在另一个地方使用否定。

Predicate<Test> specialTestPred = t -> t.getId.equals(specialId); 

Stream<Test> specialTestStream = list.stream.filter(specialTestPred); 
Stream<Test> nonSpecialTestStream = list.stream.filter(specialTestPred.negate()) 
        .sorted(Comparator.comparing(Test::getName)); 

List<Test> result = Stream.concat(specialTestStream , nonSpecialTestStream) 
          .collect(Collectors.toList()); 
+0

感谢提到它。我将不得不找出谓词。 –

0

你可以在一个排序中做。

public static void main(String[] args) { 
    String specialId = "t2"; 

    List<Test> list = new ArrayList<>(); 

    Test test1 = new Test(); 
    test1.setId("t1"); 
    test1.setName("tester1"); 
    list.add(test1); 

    Test test2 = new Test(); 
    test2.setId("t2"); 
    test2.setName("tester2"); 
    list.add(test2); 

    Test test3 = new Test(); 
    test3.setId("t3"); 
    test3.setName("tester3"); 
    list.add(test3); 

    Test test4 = new Test(); 
    test4.setId("t4"); 
    test4.setName("tester4"); 
    list.add(test4); 

    List<Test> sorted = list 
      .stream() 
      .sorted((t1, t2) -> { 
       if (t1.getId().equals(specialId)) { 
        return -1; 
       } 

       if (t2.getId().equals(specialId)) { 
        return 1; 
       } 

       return t1.getId().compareTo(t2.getId()); 
      }) 
      .collect(Collectors.toList()); 

    sorted.forEach(System.out::println); 
} 

static class Test { 
    String id; 
    String name; 

    public String getId() { 
     return id; 
    } 

    public void setId(String id) { 
     this.id = id; 
    } 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    @Override 
    public String toString() { 
     return "Test{" + 
       "id='" + id + '\'' + 
       ", name='" + name + '\'' + 
       '}'; 
    } 
} 
+0

感谢您的反馈 –

5

您可以将特殊ID处理放入比较器中。两种比较可以使用thenComparing进行链接。

  1. 首先检查ID≠特殊ID。由于false < true,这会在所有内容之前带来特殊ID。
  2. 然后按名称排序。

Stream<Test> s = list.stream().sorted(
    Comparator.comparing((Test t) -> !t.getId().equals(specialId)) 
       .thenComparing(Test::getName) 
); 
+1

原始代码有一点点不同。在原始代码中,具有特殊id的元素没有相对于彼此排序(如果有多个)。但假设id是唯一的,这不会是一个问题。 – Holger

+0

谢谢你的代码。例如,如果条件't1是最后'被添加了怎么办? –

+0

@jakehan如果你有多个特殊ID,也许你应该创建一个'int getIdRank(){return(0 if't2',2 if't1',1 else)}',然后'Comparator.comparingInt(Test :: getIdRank).thenComparing(测试::的getName)'。甚至可以将ID更改为实现Comparable的自定义类。 – kennytm

相关问题