Java8操作List
利用java8新特性,可以用简洁高效的代码来实现一些数据处理。
大致包含以下内容:
- 遍历(5种方式)
- 排序(普通排序、单/多属性排序)
- 转Map
- 分组
- 去重(对象属性去重)
- 提取
- 过滤(单条件、多条件)
- 取值(平均值、最大/最小值、求和)
1.遍历
//方式一.java 8 Lambda 遍历,stu 代表List里的Student对象
studentList.forEach(stu -> {
System.out.println(stu);
});
//方式二.java 8
studentList.forEach(System.out::println);
//方式三. for Each 遍历
for (Student stu : studentList) {
System.out.println(stu);
}
//方式四
for (int i = 0; i < studentList.size(); i++) {
System.out.println(studentList.get(i));
}
//方式五. 迭代器遍历
Iterator<Student> iterator = studentList.iterator();
while (iterator.hasNext()) {
Student next = iterator.next();
System.out.println(next);
}
2.排序
单属性排序
// 1.根据年龄升序
List<Student> ageAscList = studentList.stream()
.sorted(Comparator.comparing(Student::getAge)).collect(Collectors.toList());
// 2.根据年龄降序
List<Student> ageDescList = studentList.stream()
.sorted(Comparator.comparing(Student::getAge).reversed()).collect(Collectors.toList());
多属性排序
//根据年龄正序且创建时间倒叙
List<Student> sortedByAgeAndTime1 = studentList.stream()
.sorted(Comparator.comparing(Student::getAge).
thenComparing(Student::getCreateTime,Comparator.reverseOrder()))
.collect(Collectors.toList());
3.转map
/**
* List -> Map
* 需要注意的是:toMap 如果集合对象有重复的key,会报错Duplicate key ....
* 可以用 (k1,k2)->k1 来设置,如果有重复的key,则保留key1,舍弃key2
*/
Map<Integer, Student> userMap = studentList.stream()
.collect(Collectors.toMap(Student::getAge, a -> a, (k1, k2) -> k1));
4.分组
//List 以ID分组 Map<Integer,List<Apple>>
Map<Integer, List<Apple>> groupBy = studentList.stream().collect(Collectors.groupingBy(Apple::getId));
5.去重
通过hashSet去重(如将classNames去重):该种去重是bean完全相同的时候算重复数据
List<String> classNameList = new ArrayList(new HashSet(classNames));
第一种: 单属性去重
List<Person> unique = studentList.stream().collect(
collectingAndThen(
toCollection(() -> new TreeSet<>(comparingLong(Apple::getId))), ArrayList::new));
第二种: 单属性去重
List<Date> dateList = studentList.stream()
.map(BizLinkEcconnectSpconnectImport::getAdate)
.distinct().collect(Collectors.toList());
第三种: 多属性去重
List<ClassEntity> distinctClass = studentList.stream()
.collect(Collectors.collectingAndThen(
Collectors.toCollection(() -> new TreeSet<>(
Comparator.comparing(o -> o.getProfessionId() + ";" + o.getGrade()))), ArrayList::new));
第三种: list的String数组去重
List<String> fff = studentList.stream().distinct().collect(Collectors.toList());
6.提取
List<String> stIdList1 = studentList.stream().map(Person::getId).collect(Collectors.toList());
提取出list对象中的一个属性并去重
List<String> stIdList2 = studentList.stream().map(Person::getId).distinct().collect(Collectors.toList());
7.过滤
//单条件过滤出符合条件的数据
List<Apple> filterList = studentList.stream().filter(a -> a.getName().equals("香蕉")).collect(Collectors.toList());
//多条件
List<Student> studentFilterList = studentList.stream()
.filter(stu -> { //多种条件过滤
if (10 == stu.getAge() && "大白".equals(stu.getName())) {
return true;
}
return false;
}).collect(Collectors.toList()); //输出流收集回List中,为空的情况下返回空集合
8.取值
// 平均数
double asDouble = studentList.stream().mapToLong(Student::getAge).average().getAsDouble();
System.out.println("average:" + asDouble);
double avg = studentList.stream().collect(Collectors.averagingLong(Student::getAge));
System.out.println("average:" + avg);
// 最大值
long asLong = studentList.stream().mapToLong(Student::getAge).max().getAsLong();
Optional<Dish> maxDish = Dish.menu.stream().
collect(Collectors.maxBy(Comparator.comparing(Dish::getCalories)));
maxDish.ifPresent(System.out::println);
// 最小值
long asLong1 = studentList.stream().mapToLong(Student::getAge).min().getAsLong();
Optional<Dish> minDish = Dish.menu.stream().
collect(Collectors.minBy(Comparator.comparing(Dish::getCalories)));
minDish.ifPresent(System.out::println);
// 求和
long sum1 = studentList.stream().mapToLong(Student::getAge).sum();
//计算 总金额
BigDecimal totalMoney = studentList.stream().map(Apple::getMoney).reduce(BigDecimal.ZERO, BigDecimal::add);
常用api
1.filter
这是一个Stream的过滤转换,此方法会生成一个新的流,其中包含符合某个特定条件的所有元素,filter接受一个函数作为参数,该函数用Lambda表达式表示
2.map
map方法指对一个流中的值进行某种形式的转换。需要传递给它一个转换的函数作为参数
3.flatMap
将多个Stream连接成一个Stream,这时候不是用新值取代Stream的值,与map有所区别,这是重新生成一个Stream对象取而代之
4.limit方法和skip方法
limit(n)方法会返回一个包含n个元素的新的流(若总长小于n则返回原始流)
skip(n)方法正好相反,它会丢弃掉前面的n个元素
用limit和skip方法一起使用就可以实现日常的分页功能:
5.distinct方法和sorted方法
distinct方法会根据原始流中的元素返回一个具有相同顺序、去除了重复元素的流,这个操作显然是需要记住之前读取的元素。
sorted方法是需要遍历整个流的,并在产生任何元素之前对它进行排序。因为有可能排序后集合的第一个元素会在未排序集合的最后一位。
6.Collect
collect在流中生成列表,map,等常用的数据结构
将一个流收集到一个List中,只需要这样写就可以。
List<Integer> thereList = hereList.stream().collect(Collectors.toList());
收集到Set中可以这样用
Set<Integer> thereSet = hereList.stream().collect(Collectors.toSet());
收集到Set时,控制Set的类型,可以这样。
TreeSet<Integer> treeSet = hereList.stream()
.collect(Collectors.toCollection(TreeSet::new));
7.聚合操作
聚合是指将流汇聚为一个值,以便在程序中使用。聚合方法都是终止操作,聚合方法包括sum,count,max,min
findFirst方法返回非空集合中的第一个值,它通常与filter方法结合起来使用
Integer first = hearList.stream().filter(i->i>100).findFirst().get();
findAny方法可以在集合中只要找到任何一个所匹配的元素,就返回,此方法在对流并行执行时十分有效
Integer anyItem = hearList.parallelStream().filter(i->i>100).findAny().get();
8.分组
对具有相同特性的值进行分组是一个很常见的功能