import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
@Getter
public class CollectionUtils {
public static <T1, T2> CompareResult<T1, T2> compare(List<T1> list1, Function<T1, String> f1, List<T2> list2, Function<T2, String> f2) {
Set<String> key1Set = list1.stream().map(f1).collect(Collectors.toSet());
Set<String> key2Set = list2.stream().map(f2).collect(Collectors.toSet());
List<T1> uf1 = list1.stream().filter(i -> !key2Set.contains(f1.apply(i))).collect(Collectors.toList());
List<T2> uf2 = list2.stream().filter(i -> !key1Set.contains(f2.apply(i))).collect(Collectors.toList());
List<T1> bf1 = list1.stream().filter(i -> key2Set.contains(f1.apply(i))).collect(Collectors.toList());
List<T2> bf2 = list2.stream().filter(i -> key1Set.contains(f2.apply(i))).collect(Collectors.toList());
return new CompareResult<>(uf1, uf2, bf1, bf2);
}
@Getter
@AllArgsConstructor
public static class CompareResult<T1, T2> {
private final List<T1> uf1;
private final List<T2> uf2;
private final List<T1> bf1;
private final List<T2> bf2;
}
public static void main(String[] args) {
/// list1
T1 user1 = new T1("1", "Allen");
T1 user2 = new T1("2", "Brian");
T1 user3_1 = new T1("3", "Caroline_1");
T1 user3_2 = new T1("3", "Caroline_2");
/// list2
T2 user3_3 = new T2("3", "Caroline_1 New");
T2 user3_4 = new T2("3", "Caroline_2 New");
T2 user4 = new T2("4", "David");
T2 user5 = new T2("5", "Elisa");
List<T1> list1 = new ArrayList<>(Arrays.asList(user1, user2, user3_1, user3_2));
List<T2> list2 = new ArrayList<>(Arrays.asList(user4, user5, user3_3, user3_4));
System.out.println("list1 before: " + list1);
System.out.println("list2 before: " + list2);
CompareResult<T1, T2> compareResult = compare(list1, T1::getId, list2, T2::getId);
System.err.println("uf1: " + compareResult.getUf1());
System.err.println("uf2: " + compareResult.getUf2());
System.err.println("bf1: " + compareResult.getBf1());
System.err.println("bf2: " + compareResult.getBf2());
}
}
import lombok.Getter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
public class CollectionUtils {
@FunctionalInterface
public interface ListComparator<T1, T2> {
boolean isEquals(T1 t1, T2 t2);
}
public static <T1, T2> ListResult<T1, T2> compare2list(List<T1> t1List, List<T2> t2List, ListComparator<T1, T2> listComparator) {
List<T1> listT1 = new ArrayList<>();
List<T2> listT2 = new ArrayList<>();
Iterator<T1> itT1 = t1List.iterator();
while (itT1.hasNext()) {
T1 t1 = itT1.next();
Iterator<T2> itT2 = t2List.iterator();
while (itT2.hasNext()) {
T2 t2 = itT2.next();
if (listComparator.isEquals(t1, t2)) {
listT1.add(t1);
listT2.add(t2);
try {
itT2.remove();
itT1.remove();
} catch (UnsupportedOperationException e) {
throw new RuntimeException("only support modifiable collection");
}
}
}
}
return new ListResult<>(t1List, t2List, listT1, listT2);
}
@Getter
public static class ListResult<T1, T2> {
private final List<T1> onlyInNew;
private final List<T2> onlyInOld;
private final List<T1> bothFromT1;
private final List<T2> bothFromT2;
public ListResult(List<T1> onlyInNew, List<T2> onlyInOld, List<T1> bothFromT1, List<T2> bothFromT2) {
this.onlyInNew = onlyInNew;
this.onlyInOld = onlyInOld;
this.bothFromT1 = bothFromT1;
this.bothFromT2 = bothFromT2;
}
}
public static void main(String[] args) {
T2 t1 = new T2(1L, 10, "A");
T2 t2 = new T2(2L, 10, "B");
T2 t3_1 = new T2(3L, 10, "C");
T1 t3_2 = new T1(3L, 20, "C New");
T1 t4 = new T1(4L, 10, "D");
T1 t5 = new T1(5L, 10, "E");
List<T1> t1List = new ArrayList<>(Arrays.asList(t4, t5, t3_2));
List<T2> t2List = new ArrayList<>(Arrays.asList(t1, t2, t3_1));
System.out.println("t1List: " + t1List);
System.out.println("t2List: " + t2List);
ListResult<T1, T2> listResult = compare2list(t1List, t2List, (o1, o2) -> o1.getId().equals(o2.getId()));
System.err.println("onlyInNew: " + listResult.getOnlyInNew());
System.err.println("onlyInOld: " + listResult.getOnlyInOld());
System.err.println("bothFromT1: " + listResult.getBothFromT1());
System.err.println("bothFromT2: " + listResult.getBothFromT2());
}
}
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class T1 {
private Long id;
private Integer age;
private String name;
}