集合的泛型是集合,然后在外集合找重复的子集合
问题:
- 集合A的泛型是集合B,子集合B泛型是自定义对象,判定新增的集合C在集合A中是否有重复的子集合。
解决方法:
- 判断是否包含使用retainAll,如果A.retainAll(C),A中有数据,表示有重复数据
两种使用
-
如果集合泛型是自定义对象,使用retainAll(),最终调用的方法是
自定义对象的equals方法
。比较的是属性值是否相同public int indexOf(Object o) { int index = 0; if (o == null) { for (Node<E> x = first; x != null; x = x.next) { if (x.item == null) return index; index++; } } else { // 遍历每个元素【自定义对象】 for (Node<E> x = first; x != null; x = x.next) { // 调用自定义对象的equals方法 if (o.equals(x.item)) return index; index++; } } return -1; }
// 比较属性值是否相同 public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Stu stu = (Stu) o; return Objects.equals(name, stu.name) && Objects.equals(age, stu.age) && Objects.equals(createTime, stu.createTime); }
-
如果A集合泛型是子集合,在使用retainAll(),方法判断逻辑是遍历集合A,获取每一个子集合,判断子集合与新增的集合B是否相同。判断逻辑是调用的
父类的AbstractList中的equals方法
,该方法会判断每一个集合与新增的集合列表长度是否相同,按照顺序一一调用元素的equals方法比较数据是否相同(集合的第一个元素与另外一个集合第一个元素是否相同,集合的第二个元素与另外一个集合第二个元素是否相同……)。这里要注意两个集合添加的元素要一一对应。如果拿到的数据不是一一对应,那比较的结果就是false。在判断新增的C中里面的数据是乱序的。如果有一种方法,我们对请求添加的元素进行排好序,对已经存在的所有列表中的元素都进行排序就可以解决。这时候就用到了重写hashcode,可以使用Comparator对元素的hashcode进行排序,因为重写后的hashcode值是通过属性值计算得到的,如果两个对象即使是不同的对象(new出来的),但是属性值是相同的,那么它们的hashcode值也是一样的,这样就满足了我们的业务要求
AbstractList中的equals方法
public boolean equals(Object o) { if (o == this) return true; if (!(o instanceof List)) return false; ListIterator<E> e1 = listIterator(); ListIterator<?> e2 = ((List<?>) o).listIterator(); // 比较集合A与集合B中按照次序比较元素是否相同 while (e1.hasNext() && e2.hasNext()) { E o1 = e1.next(); Object o2 = e2.next(); if (!(o1==null ? o2==null : o1.equals(o2))) return false; } // 长度是否相同 return !(e1.hasNext() || e2.hasNext()); }
最终解决方案:
1. 使用hashcode对每一个子集合进行排序,保证子集合元素按照一定顺序排列 2. 使用equals方法进行比较数据是否相同
案例一
import java.util.LinkedList; import java.util.List; /** * @Description: * @Author party-abu * @Date 2021/12/26 20:51 */ public class TestSimpleList { public static void main(String[] args) { List<Stu> numListInnerOne = new LinkedList<>(); Stu stu01 = new Stu(); stu01.setAge(19); stu01.setName("张三"); Stu stu03 = new Stu(); stu03.setAge(33); stu03.setName("张三1"); numListInnerOne.add(stu01); numListInnerOne.add(stu03); System.out.println("========================="); List<Stu> numListInnerTwo = new LinkedList<>(); Stu stu02 = new Stu(); stu02.setAge(19); stu02.setName("张三"); Stu stu04 = new Stu(); stu04.setAge(33); stu04.setName("张三1"); numListInnerTwo.add(stu02); numListInnerTwo.add(stu04); // 取交集 numListInnerOne.retainAll(numListInnerTwo); System.out.println(numListInnerOne.size() > 0 ? "包含" : "不包含"); } }
案例二
import java.util.*; /** * @Description: * @Author party-abu * @Date 2021/12/26 20:51 */ public class TestComplex { public static void main(String[] args) { List<List<Stu>> numListOut = new LinkedList<>(); List<Stu> numListInnerOne = new LinkedList<>(); Stu stu01 = new Stu(); stu01.setAge(19); stu01.setName("张三"); numListInnerOne.add(stu01); Stu stu02 = new Stu(); stu02.setAge(22); stu02.setName("小明"); numListInnerOne.add(stu02); numListInnerOne.sort(Comparator.comparingInt(Stu::hashCode)); List<Stu> numListInnerTwo = new LinkedList<>(); Stu stu03 = new Stu(); stu03.setAge(20); stu03.setName("李四"); numListInnerTwo.add(stu03); numListOut.add(numListInnerOne); numListOut.add(numListInnerTwo); System.out.println("================================================"); List<Stu> numListInnerRequest = new LinkedList<>(); Stu stu04 = new Stu(); stu04.setAge(19); stu04.setName("张三"); Stu stu05 = new Stu(); stu05.setAge(22); stu05.setName("小明"); numListInnerRequest.add(stu04); numListInnerRequest.add(stu05); // 不进行排序,调换上边两个stu04、stu05顺序结果会不一样 numListInnerRequest.sort(Comparator.comparingInt(Stu::hashCode)); List<List<Stu>> listList = new LinkedList<>(); listList.add(numListInnerRequest); // 取交集 numListOut.retainAll(listList); System.out.println(numListOut.size() > 0 ? "包含" : "不包含"); } }