Java Stream 流常用方法 lambda 表达式实现交集、并集、差集、去重复并集等

一般的javaList 交、并集采用简单的 removeAll retainAll 等操作,不过这也破坏了原始的javaList对象,采用java8 lambda表达式流操作则可以不影响原始list对象而得到两个javaList对象的 交、并、差集。

1、分组

// 按照sn分组:  List<Map<String, Object>> dataList
Map<String, List<Map<String, Object>>> dataMap = dataList.stream().collect(Collectors.groupingBy(e -> e.get("sn") + ""));	

//按照职员部分分组: List<Employee> list
Map<String, List<Employee>> collect = list.stream().collect(Collectors.groupingBy(i -> i.getUnitName()));

//多条件分组
Map<String, Map<String,List<Employee>>> collect =list.stream().collect(Collectors.groupingBy(i -> i.getUnitName(),Collectors.groupingBy(i -> i.getWorkType())));

//按年龄分组,年龄相同的是一组
Map<Integer, List<Person>> 分组 = list.stream().collect(Collectors.groupingBy(Person::getAge));

//按年龄分组后按工资分组,多级分组
Map<Integer, Map<String, List<Person>>> 多级分组 = list.stream().collect(Collectors.groupingBy(Person::getAge, Collectors.groupingBy(x -> {
	return x.getSalary() > 3000 ? "高" : "低";
})));
 
// 分组排序 ,拿已经排好序的过来分组
LinkedHashMap<String, List<AttendanceRuleGroup>> groupingByruleGroupList = list.stream().collect(Collectors.groupingBy(AttendanceRuleGroup::getCategory, LinkedHashMap::new, Collectors.toList()));

// 分组排序,集合没排序,我们自己按我们想要的排序
LinkedHashMap<String, List<AttendanceRuleGroup>> groupingByruleGroupList = list.stream().sorted(Comparator.comparingLong(AttendanceRuleGroup::getSort).reversed()).collect(Collectors.groupingBy(AttendanceRuleGroup::getCategory, LinkedHashMap::new, Collectors.toList()));

2、过滤

//根据指定sn,过滤出符合的数据: List<Map<String, Object>> deviceDataList
List<Map<String, Object>> tempDeviceDataList = deviceDataList.stream().filter(map -> map.get("sn").toString().equals(sn)).collect(Collectors.toList());

//筛选出工资大于10000的职员
List<Employee> newList = list.stream().filter(item -> {
			return item.getSalary().compareTo(new BigDecimal(10000)) > 0 && !item.getWorkType().equals("项目经理");
		}).collect(Collectors.toList());

3、List map互转

// (k1,k2)->k2 避免键重复 k1-取第一个数据;k2-取最后一条数据
//key和value,都可以根据传入的值返回不同的Map
Map<String, String> deviceMap = list.stream().collect(Collectors.toMap(i -> i.getDeviceNum(), j -> j.getDeviceName(), (k1, k2) -> k1));

Map<String, Object> map = list.stream().collect(Collectors.toMap(i -> i.getEmpName() + i.getUnitName(), j -> j, (k1, k2) -> k1));

//在.map里面构造数据 return什么数据就转成什么类型的list
List<Employee> collect = map.entrySet().stream().map(item -> {
			Employee employee = new Employee();
			employee.setId(item.getKey());
			employee.setEmpName(item.getValue());
			return employee;
		}).collect(Collectors.toList());

4、求和/极值

//在egyList里面求cols的和
public static BigDecimal getSumBig(List<Map<String,Object>> egyList, String cols){
        BigDecimal consuBig = egyList.stream()
                .filter((Map m)->StringUtils.isNotEmpty(m.get(cols)+"") && !"null".equals(String.valueOf(m.get(cols)))
                        && !"-".equals(String.valueOf(m.get(cols))))
                .map((Map m)->new BigDecimal(m.get(cols)+""))
                .reduce(BigDecimal.ZERO,BigDecimal::add);
        return consuBig;
}

//Bigdecimal求和/极值: 
BigDecimal sum = list.stream().map(Employee::getSalary).reduce(BigDecimal.ZERO,BigDecimal::add);
BigDecimal max = list.stream().map(Employee::getSalary).reduce(BigDecimal.ZERO,BigDecimal::max);

//基本数据类型求和/极值:
Integer sum = list.stream().mapToInt(Employee::getId).sum();
Long sum = list.stream().mapToLong(Employee::getId).sum();
Double sum = list.stream().mapToDouble(Employee::getId).sum();

OptionalInt optionalMax = list.stream().mapToInt(Employee::getId).max();
optionalMax.getAsInt();

5、求最大/最小值的对象

Optional<Employee> optional = list.stream().collect(Collectors.maxBy(Comparator.comparing(Employee::getId)));
 if (optional.isPresent()) { // 判断是否有值
 		Employee user = optional.get();
 }
return optional.orElse(new Employee());

6、去重

List<String> list1 = new ArrayList();
list1.add("1111");
list1.add("2222");
list1.add("3333");

List<String> list2 = new ArrayList();
list2.add("3333");
list2.add("4444");
list2.add("5555");

// 交集
List<String> intersection = list1.stream().filter(item -> list2.contains(item)).collect(toList());
System.out.println("---得到交集 intersection---");
intersection.parallelStream().forEach(System.out :: println);

// 差集 (list1 - list2)
List<String> reduce1 = list1.stream().filter(item -> !list2.contains(item)).collect(toList());
System.out.println("---得到差集 reduce1 (list1 - list2)---");
reduce1.parallelStream().forEach(System.out :: println);

// 差集 (list2 - list1)
List<String> reduce2 = list2.stream().filter(item -> !list1.contains(item)).collect(toList());
System.out.println("---得到差集 reduce2 (list2 - list1)---");
reduce2.parallelStream().forEach(System.out :: println);

// 并集
List<String> listAll = list1.parallelStream().collect(toList());
List<String> listAll2 = list2.parallelStream().collect(toList());
listAll.addAll(listAll2);
System.out.println("---得到并集 listAll---");
listAll.parallelStream().forEach(System.out :: println);

// 去重并集
List<String> listAllDistinct = listAll.stream().distinct().collect(toList());
System.out.println("---得到去重并集 listAllDistinct---");
listAllDistinct.parallelStream().forEach(System.out :: println);

System.out.println("---原来的List1---");
list1.parallelStream().forEach(System.out :: println);
System.out.println("---原来的List2---");
list2.parallelStream().forEach(System.out :: println);

//去重之后进行拼接
Srting deviceNodeStr = list.stream().distinct().collect(Collectors.joining("','"));
//直接去重返回list
List<String> deviceIdList = list.stream().distinct().collect(Collectors.toList());

7、排序

//按照时间排序 1升 -1降
Collections.sort(listFast, (p1, p2) -> {
     return String.valueOf(p1.get("time")).compareTo(p2.get("time") + "");
});

// s1-s2 升序   s2-s1降序
Collections.sort(list,(s1,s2) -> s1.getSalary().compareTo(s2.getSalary()));

//多条件排序: List<Employee> list, s1-s2 升序   s2-s1降序
list.sort(Comparator.comparing(Employee::getSalary).reversed().thenComparing(Employee::getId).reversed());

8、拼接

//将某个字段,按照某个字符串拼接
String sns = mapList.stream()
     	.map((m)->m.get("sn")+"").collect(Collectors.joining(","));
//使用场景很多,在sql里面用于组织in的值.比如:
SELECT sn,time,value FROM electric_real_time WHERE FIND_IN_SET(sn,?)
List<Map<String, Object>> dataList = JdbcUtil.getJdbcTemplate().queryForList(dataSql, sns)

List<String> strs = Arrays.asList("a","b","cd");

//连接所有内容
String str = strs.stream().collect(Collectors.joining());
System.out.println(str);
//输出:abcd

//连接所有内容,中间加一个逗号隔开
String str1 = strs.stream().collect(Collectors.joining(","));
System.out.println(str1);
//输出:a,b,cd

//连接所有内容,中间加一个逗号隔开,两边加上括号
String str2 = strs.stream().collect(Collectors.joining(",","(",")"));
System.out.println(str2);
//输出:(a,b,cd)

9、统计

//统计:和、数量、最大值、最小值、平均值: List<Employee> list
IntSummaryStatistics collect = list.stream().collect(Collectors.summarizingInt(Employee::getId));
System.out.println("和:" + collect.getSum());
System.out.println("数量:" + collect.getCount());
System.out.println("最大值:" + collect.getMax());
System.out.println("最小值:" + collect.getMin());
System.out.println("平均值:" + collect.getAverage());

//平均值
OptionalDouble average = list.stream().mapToInt(Employee::getId).average();
average.getAsDouble();

//分组后求每个分组数量
Map<Integer, Long> collect = list.stream().collect(Collectors.groupingBy(Student::getId, Collectors.counting()));

//分组后求某个字段值的和
Map<Integer, Integer> collect = list.stream().collect(Collectors.groupingBy(Student::getId, Collectors.summingInt(Student::getScore)));

// 某个值的数量
Map<BigDecimal, Long> collect = list.stream().collect(Collectors.groupingBy(i -> i.getSalary(),Collectors.counting()));
long count = mapList.stream()
     .filter((Map m)->StringUtils.isNotEmpty(m.get(cols)+""))
     .map((Map m)->new BigDecimal(m.get(cols)+""))
     .count();

10、分区


//单层分区
Map<Boolean, List<Employee>> collect = list.stream().collect(Collectors.partitioningBy(i -> i.getId() == 1));

//分区 满足条件的一个区,不满足条件的一个区
Map<Boolean, List<Person>> collect1 = list.stream().collect(Collectors.partitioningBy(e -> e.getSalary() < 2000));

//多层分区
Map<Boolean, Map<Boolean,List<Employee>>> collect = list.stream().collect(Collectors.partitioningBy(i -> i.getId() == 1,Collectors.partitioningBy(i -> i.getSalary().compareTo(new BigDecimal(20000)) == 0)));

11、截断

List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8);

//中间操作:不会执行任何操作
Stream<Integer> stream = list.stream()
		.filter(e -> {
			System.out.println("过滤 中间操作");
			return e>3;
		})
		.limit(2);

//终止操作:一次性执行全部内容,惰性求值
stream.forEach(System.out::println);

12、跳过

List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8);

//中间操作:不会执行任何操作
Stream<Integer> stream = list.stream().skip(5);

//终止操作:一次性执行全部内容,惰性求值
stream.forEach(System.out::println);

13、查找与匹配


List<Person> list = Arrays.asList(
		new Person(18,3939),
		new Person(38,9999),
		new Person(17,9999),
		new Person(19,9988),
		new Person(38,99)
);

//是否匹配所有元素 此处返回false
boolean b = list.stream().allMatch(e -> e.getAge() == 18);
System.out.println(b);

//至少匹配一个元素,此处返回true
boolean b1 = list.stream().anyMatch(e -> e.getAge() == 19);
System.out.println(b1);

//流中是否没有匹配元素,此处返回false
boolean b2 = list.stream().noneMatch(e -> e.getAge() == 19);
System.out.println(b2);

//排序后获取第一个元素
Optional<Person> first = list.stream().sorted((x, y) -> x.getAge().compareTo(y.getAge())).findFirst();
System.out.println(first);

//获取流中任意一个元素
list.stream().findAny();

//返回流中元素的总个数
list.stream().count();

//返回流中最大值 此处根据年龄比较
Optional<Person> max = list.stream().max((x, y) -> x.getAge().compareTo(y.getAge()));
System.out.println(max.get());

//返回流中最小值 此处根据年龄比较
Optional<Person> min = list.stream().min((x, y) -> x.getAge().compareTo(y.getAge()));
System.out.println(min.get());

//获取最小的年龄
Optional<Integer> age = list.stream().map(Person::getAge).min(Integer::compareTo);
System.out.println(age.get());


//获取一个并行流,并行流会使用多个线程操作流,stream()获取的是串行流,单个线程操作流
list.parallelStream();

//查找第一个元素
Optional<Dish> collect = menu.stream().filter(dish -> dish.getCalories() > 1000).findFrist();


14、收集

//取出所有年龄放到list集合中
List<Integer> toList = list.stream().map(Person::getAge).collect(Collectors.toList());

//取出所有年龄放到set集合中
Set<Integer> toSet = list.stream().map(Person::getAge).collect(Collectors.toSet());

//取出所有年龄放到hashSet集合中
HashSet<Integer> toHashSet = list.stream().map(Person::getAge).collect(Collectors.toCollection(HashSet::new));

//获取集合中元素总和
Long count = list.stream().collect(Collectors.counting());

//获取年龄平均值
Double avg = list.stream().collect(Collectors.averagingInt(Person::getAge));

//获取工资总和
Double sum = list.stream().collect(Collectors.summingDouble(Person::getSalary));

//获取工资最大值的人
Optional<Person> max = list.stream().collect(Collectors.maxBy((p1, p2) -> Double.compare(p1.getSalary(), p2.getSalary())));
System.out.println(max.get());

//获取工资最小值的人
Optional<Person> min = list.stream().collect(Collectors.minBy((p1, p2) -> Double.compare(p1.getSalary(), p2.getSalary())));
System.out.println(min.get());

//获取元素个数、总和、最小值、平均值、最大值
DoubleSummaryStatistics collect = list.stream().collect(Collectors.summarizingDouble(Person::getSalary));
System.out.println(collect);
//输出结果:DoubleSummaryStatistics{count=5, sum=34024.000000, min=99.000000, average=6804.800000, max=9999.000000}

1. 可以使用容器的构造函数来初始化容器,例如: ```c++ int arr[] = {1, 2, 3, 4, 5}; vector<int> v(arr, arr + 5); ``` 这里使用了 vector 的构造函数,第一个参数表示起始地址,第二个参数表示结束地址。 2. 迭代器是一个用来遍历容器中元素的对象。前插型迭代器 front_insert_iterator 和后插型迭代器 back_insert_iterator 用来在容器的前端和后端插入元素。使用前插型迭代器和后插型迭代器需要满足容器支持插入操作,例如 vector、deque、list 等。定义方法如下: ```c++ #include <iterator> #include <vector> #include <iostream> using namespace std; int main() { vector<int> v; front_insert_iterator<vector<int>> fii(v); back_insert_iterator<vector<int>> bii(v); for (int i = 0; i < 5; i++) { *fii = i; *bii = i; } for (auto x : v) { cout << x << " "; } cout << endl; return 0; } ``` 3. for_each 算法可以用来访问容器中的元素,需要传入一个函数对象作为参数。函数对象可以是一个函数指针、函数对象、lambda 表达式等。例如: ```c++ #include <vector> #include <algorithm> #include <iostream> using namespace std; void print(int x) { cout << x << " "; } int main() { vector<int> v = {1, 2, 3, 4, 5}; for_each(v.begin(), v.end(), print); cout << endl; return 0; } ``` 4. copy_if 算法用于将满足条件的元素拷贝到另一个容器中,需要传入源容器的起始和结束位置、目标容器的起始位置、以及一个谓词函数作为参数。例如: ```c++ #include <vector> #include <algorithm> #include <iostream> using namespace std; bool is_odd(int x) { return x % 2 == 1; } int main() { vector<int> v = {1, 2, 3, 4, 5}; vector<int> v2; copy_if(v.begin(), v.end(), back_inserter(v2), is_odd); for (auto x : v2) { cout << x << " "; } cout << endl; return 0; } ``` 5. 自定义类型可以重载比较运算符(<、==、> 等)和插入运算符(<<),以便在容器中进行排序、输出等操作。重载的目的是为了支持自定义类型的比较和输出。例如: ```c++ #include <iostream> #include <string> using namespace std; class Student { public: string name; int score; bool operator < (const Student& other) const { return score < other.score; } bool operator == (const Student& other) const { return score == other.score; } bool operator > (const Student& other) const { return score > other.score; } friend ostream& operator << (ostream& os, const Student& s) { os << s.name << ": " << s.score; return os; } }; int main() { Student s1 = {"Tom", 80}; Student s2 = {"Jerry", 90}; cout << (s1 < s2) << endl; cout << (s1 == s2) << endl; cout << (s1 > s2) << endl; cout << s1 << endl; return 0; } ``` 6. 自定义类型可以使用 max_element、min_element、max、min 等算法进行操作,前提是要满足比较运算符的定义。例如: ```c++ #include <vector> #include <algorithm> #include <iostream> using namespace std; class Student { public: string name; int score; bool operator < (const Student& other) const { return score < other.score; } bool operator == (const Student& other) const { return score == other.score; } bool operator > (const Student& other) const { return score > other.score; } }; int main() { vector<Student> v = {{"Tom", 80}, {"Jerry", 90}, {"Alice", 70}}; auto it = max_element(v.begin(), v.end()); cout << *it << endl; return 0; } ``` 7. generate 算法可以用来生成容器中的元素,需要传入一个函数对象作为参数。函数对象可以是一个函数指针、函数对象、lambda 表达式等。例如: ```c++ #include <vector> #include <algorithm> #include <iostream> using namespace std; int fib(int n) { if (n == 0 || n == 1) { return 1; } return fib(n - 1) + fib(n - 2); } int main() { vector<int> v(10); generate(v.begin(), v.end(), []() {return rand() % 100;}); for (auto x : v) { cout << x << " "; } cout << endl; generate(v.begin(), v.end(), fib); for (auto x : v) { cout << x << " "; } cout << endl; return 0; } ``` 8. remove 和 remove_if 算法用于将满足条件的元素移动到容器的末尾,并返回移动后的末尾位置。需要使用 erase 算法来真正删除元素。例如: ```c++ #include <vector> #include <algorithm> #include <iostream> using namespace std; bool is_odd(int x) { return x % 2 == 1; } int main() { vector<int> v = {1, 2, 3, 4, 5}; auto it = remove(v.begin(), v.end(), 3); v.erase(it, v.end()); for (auto x : v) { cout << x << " "; } cout << endl; vector<int> v2 = {1, 2, 3, 4, 5}; auto it2 = remove_if(v2.begin(), v2.end(), is_odd); v2.erase(it2, v2.end()); for (auto x : v2) { cout << x << " "; } cout << endl; return 0; } ``` 9. 有序序列的并集交集差集等运算可以使用 set 的集合运算操作来实现。例如: ```c++ #include <set> #include <algorithm> #include <iostream> using namespace std; int main() { set<int> s1 = {1, 2, 3, 4}; set<int> s2 = {3, 4, 5, 6}; set<int> s3; set_intersection(s1.begin(), s1.end(), s2.begin(), s2.end(), inserter(s3, s3.begin())); for (auto x : s3) { cout << x << " "; } cout << endl; set_union(s1.begin(), s1.end(), s2.begin(), s2.end(), inserter(s3, s3.begin())); for (auto x : s3) { cout << x << " "; } cout << endl; set_difference(s1.begin(), s1.end(), s2.begin(), s2.end(), inserter(s3, s3.begin())); for (auto x : s3) { cout << x << " "; } cout << endl; return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值