2017-03-03 36 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

相關問題