java8 lambda 求list最大值、最小值、平均值、求和、中位数、属性排序(空指针异常,空值排前、排后)、去重
java8 lambda 求list最大值、最小值、平均值、求和、中位数、属性排序(空指针异常,空值排前、排后)、去重
import org.junit.Test; import java.text.SimpleDateFormat; import java.util.*; import java.util.stream.Collectors; import static java.util.Comparator.comparingLong; import static java.util.stream.Collectors.*; /** * @Author: * @Date: 2018/12/12 13:08 * @Description: */ public class test { public static void main(String[] args) { List<User> list = new ArrayList<>(); list.add(new User(21L, "张三")); list.add(new User(25L, "李四")); list.add(new User(22L, "王五")); list.add(new User(19L, "赵柳")); list.add(new User(32L, "王5")); list.add(new User(29L, "王6")); list.add(new User(21L, "王7")); // 对象根据年龄属性升序排序 List<User> newList = list.stream().sorted(Comparator.comparing(User::getAge)).collect(toList()); // 对象根据年龄属性降序排序 List<User> newList = list.stream().sorted(Comparator.comparing(User::getAge).reversed()).collect(toList()); // 标识升序,再按创建日期降序 // List<BhAnnouncement> newList = announcementList.stream().sorted(Comparator.comparing(BhAnnouncement::getReadFlag).thenComparing(BhAnnouncement::getSendTime).reversed()).collect(toList()); // list遍历 newList.forEach(System.out::println); // 平均数 double asDouble = list.stream().mapToLong(User::getAge).average().getAsDouble(); System.out.println("average:" + asDouble); double avg = list.stream().collect(Collectors.averagingLong(User::getAge)); System.out.println("average:" + avg); // 最大值 long asLong = list.stream().mapToLong(User::getAge).max().getAsLong(); System.out.println("max:" + asLong); // 最小值 long asLong1 = list.stream().mapToLong(User::getAge).min().getAsLong(); System.out.println("min:" + asLong1); // 求和 long sum1 = list.stream().mapToLong(User::getAge).sum(); System.out.println("sum:" + sum1); // 提取对象属性生成list List<Long> ids = list.stream().map(User::getAge).collect(toList()); System.out.println(ids); // list升序排序 Collections.sort(ids); System.out.println(ids); // 生成中位数 Long j; if (ids.size() % 2 == 0) { j = (ids.get(ids.size() / 2 - 1) + ids.get(ids.size() / 2)) / 2; System.out.println("中位数为" + j); } else { j = ids.get(ids.size() / 2); System.out.println("中位数为" + j); } // list倒序排序 ids.sort(Comparator.reverseOrder()); System.out.println(ids); //初始化: Student student1 = new Student("1","2",90,new User("1","2",10,"11"),""); Student student2 = new Student("2","3",840,new User("4","2",10,"11"),""); Student student3 = new Student("3","4",80,new User("3","2",10,"11"),""); Student student4 = new Student("4","7",90,new User("2","2",10,"11"),""); List<Student> students = new ArrayList<>(); students.add(student1); students.add(student2); students.add(student3); students.add(student4); //根据对象的子对象中的字段排序 List<Student> studentList = students.stream() .sorted(Comparator.comparing((Function<Student,String>)student -> student.getUser().getId()).reversed()) .collect(Collectors.toList()); // 根据对象的子对象中的字段排序 排序字段值为空,空值排在前面 List<Student> studentList1 = students.stream() .sorted(Comparator.comparing((Function<Student,String>)student -> student.getUser().getId() ,Comparator.nullsLast(String::compareTo)).reversed()) .collect(Collectors.toList()); //根据对象的子对象中的字段排序 排序字段值为空,空值排在后面 List<Student> studentList2 = students.stream() .sorted(Comparator.comparing((Function<Student,String>)student -> student.getUser().getId() ,Comparator.nullsFirst(String::compareTo)).reversed()) .collect(Collectors.toList()); // 去重 List<User> users = list.stream().collect(collectingAndThen(toCollection(() -> new TreeSet<>(comparingLong(User::getAge))), ArrayList::new)); System.out.println("去重:"+users); /** * List -> Map * 需要注意的是:toMap 如果集合对象有重复的key,会报错Duplicate key .... * apple1,apple12的id都为1。可以用 (k1,k2)->k1 来设置,如果有重复的key,则保留key1,舍弃key2 */ Map<Long, User> userMap = list.stream().collect(Collectors.toMap(User::getAge, a -> a, (k1, k2) -> k1)); System.out.println(userMap); //过滤出符合条件的数据 List<User> filterList = list.stream().filter(a -> a.getName().equals("李四")).collect(toList()); System.out.println("filterList:" + filterList); List<Integer> list2 = Arrays.asList(1, 2, 3, 4, 5); int sum = list2.stream().reduce(0, (acc, value) -> acc + value); System.out.println(sum); List<Integer> result = list2.stream().filter((value) -> value > 2).collect(toList()); result.forEach(System.out::println); List<String> result2 = list2.stream().map(value -> String.format("String:%s", value)).collect(toList()); result2.forEach(System.out::println); // 用于收集统计数据的状态对象,例如count,min,max,sum和平均。 IntSummaryStatistics stats = list2.stream().mapToInt((x) -> x).summaryStatistics(); System.out.println("Max : " + stats.getMax()); System.out.println("Min: " + stats.getMin()); System.out.println("Sun: " + stats.getSum()); System.out.println("Average : " + stats.getAverage()); System.out.println("Count : " + stats.getCount()); System.out.println("toString : " + stats.toString()); } } class User { private Long age; private String name; public User(Long i, String s) { this.age = i; this.name = s; } public Long getAge() { return age; } public void setAge(Long age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "User [age=" + age + ", name=" + name + "]"; } } List<Map> maps = Lists.newArrayList( Maps.newHashMap("aa", 10, "bb", DateUtil.formatStringToDate("2020-07-30", "yyyy-MM-dd")), Maps.newHashMap("aa", 10, "bb", DateUtil.formatStringToDate("2020-07-29", "yyyy-MM-dd")), Maps.newHashMap("aa", 16, "bb", DateUtil.formatStringToDate("2020-07-28", "yyyy-MM-dd")), Maps.newHashMap("aa", 16, "bb", DateUtil.formatStringToDate("2020-07-30", "yyyy-MM-dd")), Maps.newHashMap("aa", 20, "bb", DateUtil.formatStringToDate("2020-07-31", "yyyy-MM-dd")) ); // List<Map> 使用sorted排序时,单个字段排序没有问题, 但是使用thenComparing排序多个字段就会出现问题 maps = maps.stream().sorted(Comparator.comparing(a -> Long.parseLong(a.get("aa") + ""))).collect(Collectors.toList()); maps.forEach(System.err::println); System.err.println("===================5======================"); // maps = maps.stream().sorted(Comparator.comparing(a -> Long.parseLong(a.get("aa") + "")).thenComparing(Comparator.comparing(a -> (Date) a.get("bb"), Comparator.reverseOrder()))).collect(Collectors.toList()); // 上面那种方式没法排序,但是直接使用list的sort排序却是可以的 Comparator<Map> aa = Comparator.comparing(a -> Long.parseLong(a.get("aa") + "")); Comparator<Map> bb = Comparator.comparing(a -> (Date) a.get("bb"), Comparator.reverseOrder()); maps.sort(aa.thenComparing(bb)); maps.forEach(System.err::println); //既然按照说是Java8的方式来排序,那就给一个按照java8的方式进行排序的代码吧 public class Test { public static void main(String[] args) { Map<String, Object> map = new HashMap<String, Object>(); map.put("name", "ZK"); map.put("age", 13); Map<String, Object> map2 = new HashMap<String, Object>(); map2.put("name", "ZA"); map2.put("age", 15); Map<String, Object> map3 = new HashMap<String, Object>(); map3.put("name", "CX"); map3.put("age", 20); Map<String, Object> map4 = new HashMap<String, Object>(); map4.put("name", "CX"); map4.put("age", 18); List<Map<String, Object>> list = new ArrayList<Map<String,Object>>(); list.add(map); list.add(map2); list.add(map3); list.add(map4); // 排序代码如下 List<Map<String, Object>> collect = list.stream().sorted(Comparator.comparing(Test::comparingByName) .thenComparing(Comparator.comparing(Test::comparingByAge).reversed())) .collect(Collectors.toList()); } private static String comparingByName(Map<String, Object> map){ return (String) map.get("name"); } private static Integer comparingByAge(Map<String, Object> map){ return (Integer) map.get("age"); }
用到的一些Java8的东西
主要首先是stream了,list.stream()这里是把map的List集合变成map的流
然后就是Test::comparingByName这种中间加::表示方法引用
其次就是关键的stream.sorted()方法,参数是传一个比较器Comparator,这里由JDK自带的Comparator.comparing工具方法可以帮你构建一个按照xx属性进行比较的比较器,默认是升序
然后是比较器Comparator支持thenComparing方法,表示按照一定的比较顺序把各个比较连接起来比较
其次是比较器Comparator的reversed方法,可以让比较器的原始顺序逆序,这也正好满足题主需要按照age逆序排列的要求
最后就是collect()方法,把流的数据按照一定的方式收集起来,参数是一个收集器collector,这里用的是JDK自带的工具方法Collectors.toList把流的数据收集为集合