高效率的集合交集(差集)处理方式
https://blog.csdn.net/Yunwei_Zheng/article/details/105955777
https://blog.csdn.net/dulinanaaa/article/details/85234279
/**
* 交集(差集)处理方式(String)
* @param list1
* @param list2
* @return
*/
private List<String> getRetainAllString(List<String> list1, List<String> list2){
List<String> r = new ArrayList<>();
Map<String, String> map1 = list1.stream().collect(Collectors.toMap(s -> s, Function.identity()));
list2.stream().forEach(s -> {
String ss = map1.get(s);
if (ss != null) {
r.add(ss);
}
});
return r;
}
/**
* 交集(差集)处理方式(Integer)
* @param list1
* @param list2
* @return
*/
private List<Integer> getRetainAllInteger(List<Integer> list1, List<Integer> list2){
List<Integer> r = new ArrayList<>();
Map<Integer, Integer> map1 = list1.stream().collect(Collectors.toMap(s -> s, Function.identity()));
list2.stream().forEach(s -> {
Integer ss = map1.get(s);
if (ss != null) {
r.add(ss);
}
});
return r;
}
public static void main(String[] args) {
List<String> list1 = new ArrayList<>();
List<String> list2 = new ArrayList<>();
// 初始化数据
for (int i = 0; i < 60000; i++) {
list1.add("test" + i);
list2.add("test" + i * 3);
}
//System.out.println(list1);
//System.out.println(list2);
System.out.println("-------------------------");
long t = System.currentTimeMillis();
List<String> needAddOpenidList = getRemoveAllString(list1, list2);
System.out.println(needAddOpenidList);
System.out.println(System.currentTimeMillis() - t);
System.out.println(needAddOpenidList.size());
System.out.println("------------------");
long t1 = System.currentTimeMillis();
list1.removeAll(list2);
System.out.println(System.currentTimeMillis() - t1);
System.out.println(list1.size());
/*List<String> needAddOpenidList1 = getRemoveAllString(list2, list1);
System.out.println(needAddOpenidList1);*/
}
private static List<String> getRemoveAllString(List<String> allOpenidList, List<String> dbOpenidList) {
if (dbOpenidList != null && !dbOpenidList.isEmpty()) {
Map<String, String> dataMap = new HashMap<>();
for (String id : dbOpenidList) {
dataMap.put(id, id);
}
List<String> newList = new ArrayList<>();
for (String id : allOpenidList) {
if (!dataMap.containsKey(id)) {
newList.add(id);
}
}
return newList;
} else {
return allOpenidList;
}
}
private static List<Integer> getRemoveAllInteger(List<Integer> allOpenidList, List<Integer> dbOpenidList) {
if (dbOpenidList != null && !dbOpenidList.isEmpty()) {
Map<Integer, Integer> dataMap = new HashMap<>();
for (Integer id : dbOpenidList) {
dataMap.put(id, id);
}
List<Integer> newList = new ArrayList<>();
for (Integer id : allOpenidList) {
if (!dataMap.containsKey(id)) {
newList.add(id);
}
}
return newList;
} else {
return allOpenidList;
}
}
/**
* 产品服务收款方式
* @param params
* @return
*/
@Override
public List<MemberProductPaymentDTO> getMemberProductPayment(QueryDTO params) {
QueryDTO dto = getParams(params);
List<MemberProductPaymentDTO> yptList = extendedMapper.getMemberProductPayment(dto);
List<MemberProductPaymentEasDTO> easList = extendedEasMapper.getMemberProductPayment(dto);
List<MemberProductPaymentDTO> list = new ArrayList<>();
if (CollectionUtils.isEmpty(yptList) && CollectionUtils.isEmpty(easList)) {
return list;
}
List<Integer> list1 = yptList.stream().map(MemberProductPaymentDTO::getId).collect(Collectors.toList());
List<Integer> list2 = easList.stream().map(MemberProductPaymentEasDTO::getIdEas).collect(Collectors.toList());
Map<Integer, MemberProductPaymentDTO> mapYpt = yptList.stream().collect(Collectors.toMap(w -> w.getId(), w -> w));
Map<Integer, MemberProductPaymentEasDTO> mapEas = easList.stream().collect(Collectors.toMap(w -> w.getIdEas(), w -> w));
Integer checkResult = params.getCheckResult();
//查询状态为 全部或正确
if (!Objects.equals(CheckTypeEnum.NO.getValue(), checkResult)) {
//求交集
List<Integer> retainAllInteger = getRetainAllInteger(list1, list2);
for (int i = 0; i < retainAllInteger.size(); i++) {
Integer s = retainAllInteger.get(i);
MemberProductPaymentDTO memberProductPaymentDTO = mapYpt.get(s);
MemberProductPaymentEasDTO memberProductPaymentEasDTO = mapEas.get(s);
if (memberProductPaymentEasDTO != null) {
BeanUtils.copyProperties(memberProductPaymentEasDTO, memberProductPaymentDTO);
}
memberProductPaymentDTO.setCheckResult(CheckTypeEnum.YES.getValue());
memberProductPaymentDTO.setDateSort(memberProductPaymentDTO.getPayTime());
list.add(memberProductPaymentDTO);
}
}
//查询状态为 全部或有误
if (!Objects.equals(CheckTypeEnum.YES.getValue(), checkResult)) {
//云平台有,EAS没有
List<Integer> removeAllInteger1 = getRemoveAllInteger(list1, list2);
for (int i = 0; i < removeAllInteger1.size(); i++) {
Integer s = removeAllInteger1.get(i);
MemberProductPaymentDTO memberProductPaymentDTO = mapYpt.get(s);
memberProductPaymentDTO.setCheckResult(CheckTypeEnum.NO.getValue());
memberProductPaymentDTO.setCheckRemarks(Consts.EASDES);
memberProductPaymentDTO.setDateSort(memberProductPaymentDTO.getPayTime());
list.add(memberProductPaymentDTO);
}
//云平台没有,EAS有
List<Integer> removeAllInteger2 = getRemoveAllInteger(list2, list1);
for (int i = 0; i < removeAllInteger2.size(); i++) {
Integer s = removeAllInteger2.get(i);
MemberProductPaymentDTO memberProductPaymentDTO = new MemberProductPaymentDTO();
MemberProductPaymentEasDTO memberProductPaymentEasDTO = mapEas.get(s);
if (memberProductPaymentEasDTO != null) {
BeanUtils.copyProperties(memberProductPaymentEasDTO, memberProductPaymentDTO);
}
memberProductPaymentDTO.setCheckResult(CheckTypeEnum.NO.getValue());
memberProductPaymentDTO.setCheckRemarks(Consts.YPTDES);
memberProductPaymentDTO.setDateSort(memberProductPaymentEasDTO.getPayTimeEas());
list.add(memberProductPaymentDTO);
}
}
//排序和分页
if (CollectionUtils.isNotEmpty(list)) {
list = list.stream().sorted(Comparator.comparing(MemberProductPaymentDTO::getDateSort).reversed()).collect(Collectors.toList());
}
return list;
}
/**
* 查询转换
* @param params
* @return
*/
private QueryDTO getParams(QueryDTO params){
QueryDTO pa = new QueryDTO();
BeanUtils.copyProperties(params, pa);
pa.emptyPage();
return pa;
}
/**
* 交集处理方式(String)
* @param list1
* @param list2
* @return
*/
private List<String> getRetainAllString(List<String> list1, List<String> list2){
List<String> r = new ArrayList<>();
Map<String, String> map1 = list1.stream().collect(Collectors.toMap(s -> s, Function.identity()));
list2.stream().forEach(s -> {
String ss = map1.get(s);
if (ss != null) {
r.add(ss);
}
});
return r;
}
/**
* 交集处理方式(Integer)
* @param list1
* @param list2
* @return
*/
private List<Integer> getRetainAllInteger(List<Integer> list1, List<Integer> list2){
List<Integer> r = new ArrayList<>();
Map<Integer, Integer> map1 = list1.stream().collect(Collectors.toMap(s -> s, Function.identity()));
list2.stream().forEach(s -> {
Integer ss = map1.get(s);
if (ss != null) {
r.add(ss);
}
});
return r;
}
/**
* 差集处理方式(String)
* @param list1
* @param list2
* @return
*/
private static List<String> getRemoveAllString(List<String> list1, List<String> list2) {
if (CollectionUtils.isNotEmpty(list2)) {
Map<String, String> dataMap = new HashMap<>(list2.size());
for (String id : list2) {
dataMap.put(id, id);
}
List<String> newList = new ArrayList<>();
for (String id : list1) {
if (!dataMap.containsKey(id)) {
newList.add(id);
}
}
return newList;
} else {
return list1;
}
}
/**
* 差集处理方式(Integer)
* @param list1
* @param list2
* @return
*/
private static List<Integer> getRemoveAllInteger(List<Integer> list1, List<Integer> list2) {
if (CollectionUtils.isNotEmpty(list2)) {
Map<Integer, Integer> dataMap = new HashMap<>(list2.size());
for (Integer id : list2) {
dataMap.put(id, id);
}
List<Integer> newList = new ArrayList<>();
for (Integer id : list1) {
if (!dataMap.containsKey(id)) {
newList.add(id);
}
}
return newList;
} else {
return list1;
}
}
我们在业务上难免会遇到集合交集的处理,这边总结了几种方式比较,然后寻求最优的方式。当然如果集合数据比较少的情况下,选取的方式基本都能满足需求,但是如果在数据量比较大的情况下呢?如果选取的方式不好,那么效率就会及其的低下。下面我们就集中方式展开分析。
ArrayList原生接口retainAll(c)方式
public static void main(String[] args) {
List<String> list1 = new ArrayList<String>();
List<String> list2 = new ArrayList<String>();
List<String> r = new ArrayList<>();
// 初始化数据
for (int i = 0; i < 30000; i++) {
list1.add("test" + i);
list2.add("test" + i * 3);
}
System.out.println("添加完成");
long t = System.currentTimeMillis();
list1.retainAll(list2);
System.out.println(System.currentTimeMillis() - t);
}
我们执行上述代码,我们一个集合3w的数据,耗时时间基本都是在9s左右。
通过list遍历contains判定方式
public static void main(String[] args) {
List<String> list1 = new ArrayList<String>();
List<String> list2 = new ArrayList<String>();
List<String> r = new ArrayList<>();
for (int i = 0; i < 30000; i++) {
list1.add("test" + i);
list2.add("test" + i * 3);
}
System.out.println("添加完成");
long t = System.currentTimeMillis();
list1.stream().forEach(s->{
if(list2.contains(s)){
r.add(s);
}
});
System.out.println(System.currentTimeMillis() - t);
}
跟原生api的方式比较,效率差不多,通过代码分析,原生api也是采用的是集合遍历然后contains判定的。
List转Map通过key来判定是否交叉
public static void main(String[] args) {
List<String> list1 = new ArrayList<String>();
List<String> list2 = new ArrayList<String>();
List<String> r = new ArrayList<>();
for (int i = 0; i < 30000; i++) {
list1.add("test" + i);
list2.add("test" + i * 3);
}
System.out.println("添加完成");
long t = System.currentTimeMillis();
Map<String, String> map1 = list1.stream().collect(toMap(s -> s, Function.<String>identity()));
list2.stream().forEach(s -> {
String ss = map1.get(s);
if (ss != null) {
r.add(ss);
}
});
System.out.println(System.currentTimeMillis() - t);
}
执行代码跟上面两种方式相比,效率是相当的高,两个数组都在3W级别的数量集,基本保持在100ms左右即可完成。
原文链接:https://blog.csdn.net/Yunwei_Zheng/article/details/105955777