如何比较流中的两个列表
How to compare two lists in stream
出于训练目的,我想比较(断言等于)流中的两个列表。因此,应该比较 sampleUsers() 中的每个 id 和响应实体主体中的每个 id。我应该创建另一个流吗?如果是那么如何使用它?
@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()
}
有很多方法可以实现该断言。您可以覆盖 UserDto class.
中的 equals()
@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() 将为每个列表调用 UserDto.equals()相同位置的元素。由于 UserDto.equals() 被覆盖以仅检查 UserDto.id
,它将检查 id
而不是 Object pointer
(内存中的地址),因此返回 true。
请注意,在第二种选择中,您不能使用 int i
,因为 lambda 函数中的变量必须是最终变量。一个简单的解决方法是使用 AtomicInteger
.
一种方法是分别断言流的每个元素,这可以在以下代码的帮助下完成。您可以编写一个断言流的函数。
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 名称)
出于训练目的,我想比较(断言等于)流中的两个列表。因此,应该比较 sampleUsers() 中的每个 id 和响应实体主体中的每个 id。我应该创建另一个流吗?如果是那么如何使用它?
@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()
}
有很多方法可以实现该断言。您可以覆盖 UserDto class.
中的 equals()@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() 将为每个列表调用 UserDto.equals()相同位置的元素。由于 UserDto.equals() 被覆盖以仅检查 UserDto.id
,它将检查 id
而不是 Object pointer
(内存中的地址),因此返回 true。
请注意,在第二种选择中,您不能使用 int i
,因为 lambda 函数中的变量必须是最终变量。一个简单的解决方法是使用 AtomicInteger
.
一种方法是分别断言流的每个元素,这可以在以下代码的帮助下完成。您可以编写一个断言流的函数。
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 名称)