JDK1.8新特性之新的思考

7 篇文章 0 订阅
import java.text.Collator;
import java.util.*;
import java.util.function.BinaryOperator;
import java.util.stream.Collectors;
 
/**
 * 声明一个类时,要考虑是否要重写toString()、equals()、hashCode()、
 * 还有排序时要用的:是否要实现Comparable接口,若没有实现,是否要使用Comparator
 * 特别是涉及的集合的时候
 */
public class Person {
    public Person() {
    }
 
    public Person(String name, int age, Gender gender) {
        this.name = name;
        this.age = age;
        this.gender = gender;
    }
 
    private String name;
    private int age;
    private Gender gender;
 
    //枚举性别
    public enum Gender {
        FEMALE("女"), MALE("男");
        private String value;
 
        Gender(String value) {
            this.value = value;
        }
 
        public String getValue() {
            return value;
        }
    }
 
    public String getName() {
        return name;
    }
 
    public int getAge() {
        return age;
    }
 
    public Gender getGender() {
        return gender;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age &&
                name.equals(person.name) &&
                gender == person.gender;
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age, gender);
    }

    @Override
    public String toString() {
        return String.format("Person[name=%s,age=%d,gender=%s]%n",name,age,gender==null?"未知":gender.getValue());
    }
 

 
    public static void main(String[] args) {
       // System.out.println(Runtime.getRuntime().availableProcessors());
        List<Person> list=new ArrayList<>();
        list.add(new Person("张三",18,Person.Gender.MALE));
        list.add(new Person("张三",18,Person.Gender.MALE));
        list.add(new Person("李四",18,Person.Gender.MALE));
        list.add(new Person("赵丽",18,Person.Gender.FEMALE));
        list.add(new Person("钱婷",19,Person.Gender.FEMALE));
        list.add(new Person("田七",25, Gender.MALE));
        list.add(new Person("啊王八",25, Gender.FEMALE));
        //demo(list);
        //chineseDemo(list);
        //collectors_collectingAndThen_demo(list);
        //collectors_partitioningBy_demo(list);
        //collectors_reducing_demo(list);
        //collectors_summary_statistics_demo(list);
        collectors_to_collection_demo(list);
    }
    /**
     *将流变成集合的几种写法
     * @param list
     */
    private static void collectors_to_collection_demo(List<Person> list) {
        List<Person> personList = list.stream().collect(Collectors.toList());
        System.out.printf("返回的集合类型是:%s,该集合的元素有%s%n",personList.getClass(),personList);

        Set<Person> personSet = list.stream().collect(Collectors.toSet());
        System.out.printf("返回的集合类型是:%s,该集合的元素有%s%n",personSet.getClass(),personSet);

        //如果有重复对象,对list进行list.stream().distinct()也还是会抛异常,因为distinct()是中间操作
        // return (u,v) -> { throw new IllegalStateException(String.format("Duplicate key %s", u)); };
       // Map<Integer, String> integerStringMap = list.stream().collect(Collectors.toMap(Person::getAge, Person::getName));
        //System.out.printf("返回的集合类型是:%s,该集合的元素有%s%n",integerStringMap.getClass(),integerStringMap);

        //如果不想抛异常,改成以下写法,因为默认key一样时,不是覆盖而是抛异常
        TreeMap<Integer, String> treeMap = list.stream().collect(Collectors.toMap(Person::getAge, Person::getName, (oldValue, newValue) -> newValue, TreeMap::new));
        System.out.printf("返回的集合类型是:%s,该集合的元素有%s%n",treeMap.getClass(),treeMap);
        //元素要实现comparable才能转换成功,不然就要在构造函数里传入一个Comparator
        //TreeSet<Person> treeSet = list.stream().collect(Collectors.toCollection(TreeSet::new));
        //System.out.printf("==返回的集合类型是:%s,该集合的元素有%s%n",treeSet.getClass(),treeSet);

        //改进写法:
        TreeSet<Person> treeSet = list.stream().collect(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Person::getName))));
        System.out.printf("==返回的集合类型是:%s,该集合的元素有%s%n",treeSet.getClass(),treeSet);
    }

    /**
     * 对数据进行统计
     * 其实是将求和、平均值、最值封装到一个统计对象里面了
     * @param list
     */
    private static void collectors_summary_statistics_demo(List<Person> list) {
        IntSummaryStatistics intSummaryStatistics = list.stream().collect(Collectors.summarizingInt(Person::getAge));
        System.out.println(intSummaryStatistics.getMax());
        System.out.println(intSummaryStatistics.getMin());
        System.out.println(intSummaryStatistics.getAverage());
        System.out.println(intSummaryStatistics.getSum());
        System.out.println(intSummaryStatistics.getCount());
    }
    /**
     * 对数据进行聚合【规约、缩减、约简】
     * 其实求和、平均值、最值问题也可以用reducing
     * @param list
     */
    private static void collectors_reducing_demo(List<Person> list) {
        //要在流上执行简单的约简,可以使用stream.reduce(BinaryOperator)

        //根据年龄进行分组,分组后获得每一组的最大年龄的人
        //写法一:使用reducing
        Map<Integer, Optional<Person>> map = list.stream()
                .collect(Collectors.groupingBy(Person::getAge, Collectors.reducing(
                        BinaryOperator.maxBy(Comparator.comparing(Person::getAge)))));
        System.out.println(map);

        //写法二: 使用Collectors.maxBy,底层是调用写法一的写法
        Map<Integer, Optional<Person>> resultMap = list.stream()
                .collect(Collectors.groupingBy(Person::getAge, Collectors.maxBy( Comparator.comparing(Person::getAge))));
        System.out.println(resultMap);

        //其实求和、平均值、最值问题也可以用reducing,就像这样
        Map<Gender, Integer> result = list.stream().collect(Collectors.groupingBy(Person::getGender,
                Collectors.reducing(0, Person::getAge, Integer::sum)));//从0开始累加
        System.out.println(result);
    }


    /**
     * 对数据进行求平均值、求和,最大值、最小值
     * @param list
     */
    private static void collectors_averaging_demo(List<Person> list) {
        //求年龄的平均值Collectors.averagingDouble(), Collectors.averagingLong()
        Double ageAveraging = list.stream().collect(Collectors.averagingInt(Person::getAge));
        System.out.println(ageAveraging.doubleValue());

        //求年龄之和Collectors.summingDouble(),Collectors.summingLong()
        Integer sum = list.stream().collect(Collectors.summingInt(Person::getAge));
        System.out.println(sum);
        //最大年龄的人
        Optional<Person> maxAgePerson = list.stream().collect(Collectors.maxBy(Comparator.comparingInt(Person::getAge)));
        System.out.printf("最大年龄的人:%s%n",maxAgePerson.orElseGet(()->new Person("",-1,null)));
        //最小年龄的人
        Optional<Person> minAgePerson = list.stream().collect(Collectors.minBy(Comparator.comparingInt(Person::getAge)));
        System.out.printf("最小年龄的人:%s%n",minAgePerson.orElseGet(()->new Person("",-1,null)));

        //问题来了,如果最大年龄的人有多个呢?-- 可以这么做
        List<Person> personList = list.stream().collect(Collectors.groupingBy(Person::getAge, TreeMap::new, Collectors.toList()))
                .lastEntry().getValue();//使用TreeMap的lastEntry()方法
        System.out.printf("最大年龄的人:%s%n",personList);

    }

    /**
     * 对数据进行分区
     * @param list
     */
    private static void collectors_partitioningBy_demo(List<Person> list) {
        //对数据进行分区
        Map<Boolean, List<Person>> booleanListMap = list.stream()
                .collect(Collectors.partitioningBy(x -> x.getGender() == Gender.MALE));
        System.out.println(booleanListMap);
        对数据进行分区--后计算每个分区的数量
        Map<Boolean, Long> countPartitionMap = list.stream().collect(Collectors.partitioningBy(x -> x.getGender() == Gender.MALE, Collectors.counting()));
        System.out.println(countPartitionMap);
    }

    /**
     * 对数据进行分组--分组完后对每一个list进行排序
     * @param list
     */
    private static void collectors_collectingAndThen_demo(List<Person> list) {
        //收集完后返回一个list集合,对list集合进行按年龄【倒序】排序
      /*  List<Person> personList = list.stream().collect(Collectors.collectingAndThen(Collectors.toList(), resultList -> {
            resultList.sort(Comparator.comparing(Person::getAge).reversed());
            return resultList;
        }));
        System.out.println(personList);*/

        //分组完后对每一个list进行排序--默认使用的Map是HashMap--return groupingBy(classifier, HashMap::new, downstream);
        Map<Integer, List<Person>> listMap = list.stream().collect(Collectors.groupingBy(Person::getAge
                , Collectors.collectingAndThen(Collectors.toList(), resultList -> {
            resultList.sort(Comparator.comparing(Person::getName));
            return resultList;
        })));
        System.out.println(listMap);

        //使用TreeMap 来存储key
        TreeMap<Integer, List<String>> listTreeMap = list.stream().collect(Collectors.groupingBy(Person::getAge//根据年龄分组
                , TreeMap::new使用TreeMap 来存储key
                , Collectors.mapping(Person::getName, Collectors.toList())));//将集合中的每个元素映射成姓名
        System.out.println(listTreeMap);
    }

    /**
     * 根据中文拼音姓名排序
     * @param list
     */
    private static void chineseDemo(List<Person> list) {
        //按照姓名自然排序,姓名相同按年龄排序
        list.sort(Comparator.comparing(Person::getName).thenComparing(Person::getAge));
        //根据中文拼音姓名排序:写法一
        list.sort((p1, p2) -> Collator.getInstance(Locale.CHINA).compare(p1.getName(), p2.getName()));
        //根据中文拼音姓名排序:写法二
        //告诉程序,我要根据姓名排序,不使用默认比较器,使用我指定比较器去排序
        list.sort(Comparator.comparing(Person::getName, Collator.getInstance(Locale.CHINA)));
        list.forEach(System.out::println);
    }

    private static void demo(List<Person> list) {
        //根据中文姓名排序
        list.sort((p1,p2)-> Collator.getInstance(Locale.CHINA).compare(p1.getName(),p2.getName()));
        list.sort(Comparator.comparing(Person::getName,Collator.getInstance(Locale.CHINA)));
        //重写了toString之后,for循环够足够优雅只需要一行
        //因为打印方法的本质就是调用对象的toString()方法
        list.forEach(System.out::println);
        //注意:contains 中的对象要重写equals方法和hashCode方法
        //因为其源代码就是调用对象的equals方法
        //我们指定相同姓名相同年龄相同性别为同一对象
        System.out.println( list.contains(new Person("张三",18, Gender.MALE)));

        //去重复方式一:
        //底层是通过LinkedHashSet去重的,而LinkedHashSet是会按照原先的顺序进行迭代的
        List<Person> collect1 = list.stream().distinct().collect(Collectors.toList());
        System.out.println(collect1);
        //去重复方式二:
        //返回的是一个HashSet 无序
        Set<Person> collect = list.stream().collect(Collectors.toSet());
        System.out.println(collect);

        //根据年龄分组
        //Function<Person, Integer> getAge = Person::getAge;
        //Collector<Person, ?, Map<Integer, List<Person>>> personMapCollector = Collectors.groupingBy(Person::getAge);
        Map<Integer, List<Person>> listMap = list.stream().collect(Collectors.groupingBy(Person::getAge));
        System.out.println(listMap);

        //根据年龄分组,并且只保留人名
        Map<Integer, List<String>> listStringMap = list.stream().collect(Collectors.groupingBy(Person::getAge, Collectors.mapping(Person::getName, Collectors.toList())));

        //给定一个对象,如果该对象在list中存在,则删除
        //jdk1.8以后只需要一行,removeIf方法结合了contains方法和remove方法
        list.removeIf(e->e.equals(new Person("张三",18, Gender.MALE)));
        System.out.println(list);

        //list.indexOf()
        //list.lastIndexOf()
        //一个典型的流聚合操作就是filter-map-forEach,能否很方便地使用lambda表达式和方法引用
        list.stream().filter(p->p.getAge()==18&&p.getGender()== Gender.MALE).
                map(Person::getName).forEachOrdered(System.out::println);

        //reduction operation 减少操作(聚合操作)
        //sum方法其实就是调用reduce(0, Integer::sum)方法
        //reduce(0, Integer::sum)的第一个参数是初始值和返回结果,第一个参数会累加第二个参数的返回值
        //以下三条式子等同
        Integer totalAge = list.stream() .mapToInt(Person::getAge).sum();
        Integer reduce = list.stream().map(Person::getAge).reduce(0, (a, b) -> a + b);
        Integer reduce2 = list.stream().map(Person::getAge).reduce(0, Integer::sum);

        //lambda表达式不能访问非final的局部变量

        //检索每个性别的平均年龄
        Map<Gender, Double> collect2 = list.stream().collect(Collectors.groupingBy(Person::getGender, Collectors.averagingInt(Person::getAge)));
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值