常用List工具类(取交集、并集等等)

embedded/2024/11/17 2:08:08/

支持操作:

  • 根据指定字段,获取两个对象集合的交集、补集、并集等
  • 将对象中的多个字段值,抽取到一个List中
java">import java.lang.reflect.Field;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;/*** Description:List工具类。用于处理两个列表的交集、并集、差集等操作。** @author jiangniao* @date 2024-3-22*/
public class ListUtil {private ListUtil() {}/*** 提取多个字段的值到一个list** @param list      对象集合* @param fieldName 需要提取的字段名* @return*/public static List<String> extractFieldsToList(List<?> list, String... fieldName) {return list.stream().flatMap(item->Arrays.stream(fieldName).map(field->BeanUtils.getSimpleProperty(item, field))).collect(Collectors.toList());}/*** 根据指定字段找出两个列表的交集。** @param list1* @param list2* @param fields* @param <T>* @return*/public static <T> List<T> intersection(List<T> list1, List<T> list2, String... fields) {return list1.stream().filter(item1->containsWithFields(list2, item1, fields)).collect(Collectors.toList());}/*** 根据指定字段找出两个列表的并集** @param list1* @param list2* @param fields* @param <T>* @return*/public static <T> List<T> union(List<T> list1, List<T> list2, String... fields) {List<T> union = new ArrayList<>(list1);union.addAll(list2.stream().filter(item->!containsWithFields(list1, item, fields)).collect(Collectors.toList()));return union;}/*** 根据指定字段找出两个列表的差集。list1中有,list2中没有的元素** @param list1* @param list2* @param fields* @param <T>* @return 返回list1过滤后的数据*/public static <T> List<T> difference(List<T> list1, List<T> list2, String... fields) {return list1.stream().filter(item->!containsWithFields(list2, item, fields)).collect(Collectors.toList());}/*** 找出两个列表的差集。list1中有,list2中没有的元素。* <p>用于非Object对象的比较,比如String、Integer等** @param list1* @param list2* @param <T>* @return 返回list1过滤后的数据*/public static <T> List<T> difference(List<T> list1, List<T> list2) {list1.removeAll(list2);return list1;}/*** 辅助方法,判断列表中是否包含指定对象** @param list* @param item* @param fields* @param <T>* @return*/private static <T> boolean containsWithFields(List<T> list, T item, String... fields) {return list.stream().anyMatch(item2->matchesFields(item, item2, fields));}/*** 辅助方法,判断两个对象的指定字段是否相等** @param item1* @param item2* @param fields* @param <T>* @return*/private static <T> boolean matchesFields(T item1, T item2, String... fields) {try {for (String field : fields) {Field declaredField1 = item1.getClass().getDeclaredField(field);Field declaredField2 = item2.getClass().getDeclaredField(field);declaredField1.setAccessible(true);declaredField2.setAccessible(true);if (!Objects.equals(declaredField1.get(item1), declaredField2.get(item2))) {return false;}}return true;} catch (Exception e) {throw new RuntimeException(e);}}/*** 根据指定字段对列表进行去重** @param list* @param fields* @param <T>* @return*/public static <T> List<T> distinctByFields(List<T> list, String... fields) {return list.stream().filter(distinctByKey(t->getKey(t, fields))).collect(Collectors.toList());}/*** 辅助方法,用于生成去重的键** @param keyExtractor* @param <T>* @return*/private static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {Map<Object, Boolean> seen = new ConcurrentHashMap<>();return t->seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;}/*** 辅助方法,生成由指定字段的值组成的键** @param item* @param fields* @param <T>* @return*/private static <T> String getKey(T item, String... fields) {StringBuilder key = new StringBuilder();try {for (String field : fields) {Field declaredField = item.getClass().getDeclaredField(field);declaredField.setAccessible(true);key.append(declaredField.get(item)).append("-");}} catch (Exception e) {throw new RuntimeException(e);}return key.toString();}}

http://www.ppmy.cn/embedded/138152.html

相关文章

Linux通过端口号找到程序启动路径(Ubuntu20)

通过端口号找到程序启动路径步骤 端口号: 10020 1. 通过端口找PID 这里常用的有两种命令都可以 lsof(list open files) 和 netstat( Network Statistics) 方式一: lsof -i :10020 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME java 1178 root 119u IPv…

Vue实际应用之无限滚动、css之、混合宏和~

目录 vue-infinite-scroll 引入工程 全局配置 按需引入 使用方式 属性说明 常见问题及解决方案 CSS中的&的用法 vue中&#xff0c;import 后面的波浪号~ scss中的混合宏 直接看使用 今天来点实际的&#xff0c;看起来简单但是给我们代码带来更好的效果&#x…

Day44 | 动态规划 :状态机DP 买卖股票的最佳时机IV买卖股票的最佳时机III

Day44 | 动态规划 &#xff1a;状态机DP 买卖股票的最佳时机IV&&买卖股票的最佳时机III&&309.买卖股票的最佳时机含冷冻期 动态规划应该如何学习&#xff1f;-CSDN博客 本次题解参考自灵神的做法&#xff0c;大家也多多支持灵神的题解 买卖股票的最佳时机【…

删库跑路,启动!

起因&#xff1a;这是一个悲伤的故事&#xff0c;在抓logcat时 device待机自动回根目录了&#xff0c;而题主对当前路径的印象还停留在文件夹下&#xff0c;不小心在根目录执行了rm -rf * … 所以&#xff0c;这是个悲伤的故事&#xff0c;东西全没了…device也黑屏了&#xff…

Spring Boot框架:电商系统的设计与实现

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本网上商城系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数据信息&…

电子应用产品设计方案-9:全自动智能马桶系统设计方案

一、系统概述 本全自动智能马桶系统旨在提供舒适、卫生、便捷和智能化的如厕体验。通过融合多种传感器技术、电子控制单元和机械执行机构&#xff0c;实现马桶的自动冲洗、座圈加热、臀部清洗、烘干等功能&#xff0c;并具备智能感应、用户个性化设置和健康监测等特色功能。 二…

MySQL45讲 第二十讲 幻读是什么,幻读有什么问题?

文章目录 MySQL45讲 第二十讲 幻读是什么&#xff0c;幻读有什么问题&#xff1f;一、幻读的定义二、幻读带来的问题&#xff08;一&#xff09;语义问题&#xff08;二&#xff09;数据一致性问题 三、InnoDB 解决幻读的方法四、总结 MySQL45讲 第二十讲 幻读是什么&#xff0…

【Android、IOS、Flutter、鸿蒙、ReactNative 】启动页

Android 设置启动页 自定义 splash.xml 通过themes.xml配置启动页背景图 IOS 设置启动页 LaunchScreen.storyboard 设置为启动页 storyboard页面绘制 Assets.xcassets 目录下导入图片 AppLogo Flutter 设置启动页 Flutter Android 设置启动页 自定义 launch_background.xm…