두 리스트 비교 및 차이점 얻기
두 개의 목록이 있습니다.그것들은 서로 다른 유형의 객체를 포함하고 있지만, 두 유형 모두 id와 name을 포함하고 있으며, id는 제가 비교하고 있는 것입니다.목록 1은 DB에서 가져오고, 목록 2는 프런트엔드에서 전송됩니다.
제가 해야 할 일은 그것들을 반복해서 보고 새로 추가된 목록 항목과 삭제된 목록 항목을 찾는 것입니다.
할 수 있었지만, 문제는 보기 흉하게 생겼다는 것입니다.
예를 들어 NameDTO라고 하는 id와 name을 가질 수 있는 객체를 가지고 있다고 가정해 보겠습니다.목록 2는 해당 유형의 개체로 채워집니다.
제가 한 일은 다음과 같습니다.
final ArrayList<NamedDTO> added = new ArrayList<>();
final ArrayList<NamedDTO> removed = new ArrayList<>();
for(NamedDTO listTwoObject : listTwo) {
boolean contained = false;
for(SomeObject listOneObject : listOne) {
if(listTwoObject.getId().equals(listOneObject.getId()) {
contained = true;
}
}
if(!contained) {
added.add(listTwoObject);
}
}
for(SomeObject listOneObject : listOne) {
boolean contained = false;
for(NamedDTO listTwoObject : listTwo) {
if(listTwoObject.getId().equals(listOneObject.getId()) {
contained = true;
}
}
if(!contained) {
removed.add(new NamedDTO(listOneObject.getId(), listOneObject.getName()));
}
}
이것은 효과가 있습니다. 제가 테스트해 봤습니다.더 나은 해결책이 있습니까?비교할 수 있도록 세트를 사용하려고 했는데, 단점이 있나요?
내가 올바르게 이해한 경우 다음과 같은 시나리오가 있습니다.
- 하나의 [데이터베이스] 항목 나열:
[A, B, C, D] - [항목을 두 [앞] 항열나니합다목을:다▁list니.
[B, C, D, E, F]
효과적으로 얻을 필요가 있는 것은 다음과 같습니다.
- 추됨가:
[E, F] - 삭됨:
[A]
첫번째로, 나는 어떤 종류의 어댑터를 사용하거나 하나의 공통 클래스에서 다른 종류를 확장할 것입니다.override그자리의 equals하여 매칭할 수 .id그리고.name
두 번째로, 이것은 세트에서 매우 쉬운 작업입니다(세트의 것을 사용할 수 있지만 목록도 괜찮습니다)저는 도서관을 이용하는 것을 추천합니다: https://commons.apache.org/proper/commons-collections/apidocs/org/apache/commons/collections4/CollectionUtils.html
그리고 이제 기본적으로:
- 된 것은 가됨추입니다.
listTwo - listOne - is 제됨입니다.
listOne - listTwo
Java 코드 사용:
- 추됨가:
CollectionUtils.removeAll(listTwo, listOne) - 삭됨:
CollectionUtils.removeAll(listOne, listTwo)
그렇지 않은 에는 모든 에서 그지않모컬서에를 합니다.Collection(Java Docs) 또한 있습니다.removeAll사용할 수 있는 방법입니다.
Java 8 스트림을 사용하는 솔루션을 제안합니다.
ArrayList<ObjOne> list = new ArrayList<>(Arrays.asList(new ObjOne("1","1"),new ObjOne("3","3"),new ObjOne("2","2")));
ArrayList<ObjTwo> list2 = new ArrayList<>(Arrays.asList(new ObjTwo("1","1"),new ObjTwo("3","3"),new ObjTwo("4","4")));
List<ObjOne> removed = list.stream().filter(o1 -> list2.stream().noneMatch(o2 -> o2.getId().equals(o1.getId())))
.collect(Collectors.toList());
System.out.print("added ");
removed.forEach(System.out::println);
List<ObjTwo> added = list2.stream().filter(o1 -> list.stream().noneMatch(o2 -> o2.getId().equals(o1.getId())))
.collect(Collectors.toList());
System.out.print("removed ");
added.forEach(System.out::println);
기본적으로 이 솔루션은 스트림을 사용하여 구현되므로 코드를 더 짧고 읽기 쉽게 만들 수 있습니다.
이 중첩된 목록 처리는 보기 흉할 뿐만 아니라 비효율적입니다.당신은 한 목록의 를 한목를의 ID장것이항더좋다니습상으로 하는 것이 .Set효율적인 조회를 허용한 다음 다른 목록을 사용하여 처리합니다.Set이런 식으로, 당신은 공연을 하지 않습니다.list1.size()list2.size()단, 업작나, 러그나list1.size()플러스list2.size()연산, 이는 더 큰 목록의 경우 중요한 차이입니다.두 으로 같기 에 이렇게.
public static <A,B,R,ID> List<R> extract(
List<A> l1, List<B> l2, Function<A,ID> aID, Function<B,ID> bID, Function<A,R> r) {
Set<ID> b=l2.stream().map(bID).collect(Collectors.toSet());
return l1.stream().filter(a -> !b.contains(aID.apply(a)))
.map(r).collect(Collectors.toList());
}
이 방법은 다음과 같이 사용할 수 있습니다.
List<NamedDTO> added = extract(listTwo, listOne, NamedDTO::getId, SomeObject::getId,
Function.identity());
List<NamedDTO> removed = extract(listOne, listTwo, SomeObject::getId, NamedDTO::getId,
so -> new NamedDTO(so.getId(), so.getName()));
두 목록을 스왑하려면 도우미 메서드가 요소 유형과 독립적이어야 하므로 메서드 참조를 통해 지정할 수 있는 id 속성에 액세스하는 기능이 필요합니다.한데, 그다음런, 요를설필함요데한이, 함다항수니입등식경한우의는수가는하명소과결▁the▁in▁getting▁then▁functionjust▁identity▁is다▁element함▁describ니,수▁(▁a▁result이,는▁case입▁an▁oneing▁function그항▁the▁required).NamedDTO) 및 람다 표현식을 구성합니다.NamedDTO부터SomeObject다른 하나는
작업 자체는 위에서 설명한 것처럼 간단하며, 하나의 목록에 대해 반복하고, id에 매핑하여 다음으로 수집합니다.Set그런 다음, 다른 목록 위에 반복하고, id가 세트에 없는 요소만 유지하고, 결과 유형에 매핑하고, 다음으로 수집합니다.List.
이러한 ID가 고유한 경우 HashSet에 저장하여 관심 있는 ID를 찾을 수 있습니다.
Set<Integer> uiList = Stream.of(new FromUI(1, "db-one"), new FromUI(2, "db-two"), new FromUI(3, "db-three"))
.map(FromUI::getId)
.collect(Collectors.toCollection(HashSet::new));
Set<Integer> dbList = Stream.of(new FromDB(3, "ui-one"), new FromDB(5, "ui-five"))
.map(FromDB::getId)
.collect(Collectors.toCollection(HashSet::new));
uiList.removeIf(dbList::remove);
added/uiSet : [1,2]
removed/dbSet : [5]
내가 만든FromUI그리고.FromDBID와 이름을 입력으로 사용하는 생성자가 있는 클래스입니다.
저는 또한 만약 어떤 요소가 포함되어 있다면,uiSet하지만 이 아닌dbSet는 추가되었고 그 반대입니다.
언급URL : https://stackoverflow.com/questions/42026164/comparing-two-lists-and-getting-differences
'programing' 카테고리의 다른 글
| 테이블에서 CLOB_COLUMN을 선택합니다; (0) | 2023.07.03 |
|---|---|
| Chainable...의 매개 변수 유형 키에 인수 유형 문자열을 할당할 수 없습니다.사이프레스에서 (0) | 2023.07.03 |
| 열이 존재하지 않으면 null인 경우 columnValue를 선택합니다. (0) | 2023.07.03 |
| 열에서 구분된 문자열을 분할하고 새 행으로 삽입 (0) | 2023.07.03 |
| Spring Boot 2.3.0 - MongoDB 라이브러리가 인덱스를 자동으로 생성하지 않음 (0) | 2023.07.03 |