簡體   English   中英

如何比較stream中的兩個列表

[英]How to compare two lists in stream

為了訓練目的,我想比較(斷言等於)stream 中的兩個列表。因此,應該比較來自 sampleUsers() 的每個 id 和來自響應實體正文的每個 id。 我應該創建另一個 stream 嗎? 如果是那么如何使用它?

@Test
  void findAllUsers() {
    when(userService.findAll()).thenReturn(sampleUsers());
    ResponseEntity<List<UserDto>> responseEntity = userController.findAll();

    //first assert
    assertEquals(responseEntity.getStatusCode().value(), 200);

    //second assert
    assertEquals(responseEntity.getBody().size(), sampleUsers().size());

    //third assert
    responseEntity.getBody().stream()
          .filter(user -> user.getId() != null)
          .filter(user -> user.getUsername() != null)
          //TODO check for each user if: 
          //     user.getId is equal to id from sampleUsers() list
          //     something like: assert equals user.getId(), sampleUsers.get(0).getId()
    }

有很多方法可以做這個斷言。 您可以將 UserD 中的 equals() 重寫為 class。

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || this.getClass() != o.getClass()) return false;
    UserDto userDto = (UserDto) o;
    return this.id.equals(userDto.id);
}

並為 UserDto class 實現一個比較器。這將用於對兩個列表進行排序。

public class UserDtoComparatorById implements Comparator<UserDto> {
    @Override
    public int compare(UserDto o1, UserDto o2) {
        return o1.getId().compareTo(o2.getId());
    }
}

最后。

@Test
void findAllUsers() {
    when(userService.findAll()).thenReturn(sampleUsers());
    ResponseEntity<List<UserDto>> responseEntity = userController.findAll();

    //first assert
    assertEquals(responseEntity.getStatusCode().value(), 200);

    //second assert (this is optional)
    assertEquals(responseEntity.getBody().size(), sampleUsers().size());
   
    // to prevent false negatives, in case both lists have same objects
    // but different orders 
    Comparator<UserDto> comparator = new UserDtoComparatorById();
    sampleUsers.sort(comparator);
    responseEntity.getBody().sort(comparator);

    //third assert
    assertEquals(responseEntity.getBody(), sampleUsers);

    //same assertion but using streams
    AtomicInteger i = new AtomicInteger(0);
    assertEquals(
        list1.stream()
             .filter(user -> user.equals(list2.get(i.getAndIncrement())))
             // or: filter(user -> user.getId().equals(list2.get(i.getAndIncrement()).getId()))
             .count(), 
        list1.size()
    );
}

第三個斷言將起作用,因為兩個列表都已排序並且 assertEquals() 將為同一 position 中的每個元素調用UserDto.equals() 。由於 UserDto.equals() 被覆蓋以僅檢查UserDto.id ,它將檢查id而不是Object pointer (內存中的地址),因此返回 true。

請注意,在第二種選擇中,您不能使用int i ,因為 lambda 函數中的變量需要是最終變量。 一個簡單的解決方法是使用AtomicInteger

一種方法是分別斷言 stream 的每個元素,這可以在以下代碼的幫助下完成。 您可以編寫一個 function 來斷言流。

static void assertStreamEquals(Stream<User> s1, Stream<User> s2) {
    Iterator<Student> iter1 = s1.iterator(), iter2 = s2.iterator();
    while(iter1.hasNext() && iter2.hasNext())
        assertEquals(iter1.next().id, iter2.next().id);
    assert !iter1.hasNext() && !iter2.hasNext();
}

並通過傳遞你的兩個流來調用它。

@Test
void findAllUsers() {
    when(userService.findAll()).thenReturn(sampleUsers());
    ResponseEntity<List<UserDto>> responseEntity = userController.findAll();

    //first assert
    assertEquals(responseEntity.getStatusCode().value(), 200);

    //second assert
    assertEquals(responseEntity.getBody().size(), sampleUsers().size());

    //third assert
    assertStreamEquals(responseEntity.getBody(),sampleUsers);

(假設User為class用戶名)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM