JDK1.8学习

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Little_Red_Rose/article/details/81742164

java稀缺装备

时隔多月迎来了java学习的进阶之路。本人菜鸡一枚,写的学习笔记虽力求完美,怎无奈差强人意!这里的笔记大多是拾人牙慧,还没有来自自身的经验总结。希望以后能有机会写出自己的体会。也欢迎交流学习,虽然我知道写的东西很少有人看,哈哈。

JDK1.8新特性之Stream

集合类的应用之简单认识

首先我们新建一个员工类

package Entity;

public class Employee {

public String name;

public String address;
public int age;
public int salary;


    //    构造
    public Employee(String name,String address,int salary,int age){
        this.name = name;
        this.address = address;
        this.age = age;
        this.salary = salary;
    }

    public Employee(){
        this.name = "未知";
        this.address = "未知";
        this.age = 23;
        this.salary = 5000;
    }
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getSalary() {
        return salary;
    }

    public void setSalary(int salary) {
        this.salary = salary;
    }
    //    输出内容
    public static void show(Employee employee){
        System.out.println(employee.name+"  "+employee.address+"  "+employee.age+"  "+employee.salary);
    }

}

集合stream的简单操作如下,新建一个类:
package JDKNewFeature;

import Entity.Employee;

import java.util.Arrays;
import java.util.List;

/**
 * @ClassName StreamSimple
 * @Description TODO 多个中间操作可以连接起来形成一个流水线,除非流水想上出发终止操作。否则中间操作不会执行任何的处理,而在终止操作时一次性全部处理,成为“惰性求值”。
 * @Date 2018/7/30 14:30
 * @Version 1.0
 */
public class StreamSimple {

    /** TODO
     * 筛选和切片
     * <p>
     * filter -- 接受Lambda,从流中排除某些元素
     * limit -- 截断流,使其元素不超过某个给定数量
     * skip -- 跳过元素,返回一个扔掉了前n个元素的流,若流中元素不足n个,则返回一个空流,与limit互补。
     * distinct -- 去重,通过hashcode和equals去重。
     */
    public static void main(String[] arg) {
        List<Employee> list = Arrays.asList(
                new Employee("张三", "上海", 5000, 22),
                new Employee("李四", "北京", 4000, 23),
                new Employee("c五", "日本", 6000, 50),
                new Employee("b七", "香港", 7000, 50),
                new Employee("赵六", "纽约", 1000, 8)
        );
        //    操作开始了
        list.stream()
                .filter(e -> e.getAge() > 20)//条件过滤
                .limit(4)//不多于4个
                .skip(1)//跳过1个
                .distinct()//去重
                .forEach(e -> Employee.show(e));//遍历
    }

}

集合类应用之进阶

这里展示一下稍微复杂一点的应用场景

package JDKNewFeature;

import Entity.Employee;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName StreamCollect
 * @Description TODO  将流转换成其他格式,接受一个Collector接口的实现,用于给Stream中元素做汇总的操作。Collector接口中方法的实现决定了如何对流进行收集操作(如收集到List、Set、Map)中,Collectors实用类提供了很多静态方法,可以方便的创建常用收集器实例,具体方法见API
 * @Date 2018/7/31 9:40
 * @Version 1.0
 */
public class StreamCollect {
    public static void main(String[] args){
        List<Employee> employees = Arrays.asList(
                new Employee("张三", "上海", 5000, 22),
                new Employee("李四", "北京", 4000, 23),
                new Employee("c五", "日本", 6000, 50),
                new Employee("b七", "香港", 7000, 50),
                new Employee("赵六", "纽约", 1000, 8)
        );
        /**
         * 收集
         * collect
         * -- 将流转换成其他的形式,接收一个Collector接口的实现,可以通过Collectors的实用类操作
         */

        //收集姓名到列表
        List<String> collect = employees.stream()
                .map(Employee::getName)
                .collect(Collectors.toList());
        collect.forEach(System.out::println);
        System.out.println("-------------------------");

        //收集姓名到set
        Set<String> collect1 = employees.stream().map(Employee::getName)
                .collect(Collectors.toSet());
        collect1.forEach(System.out::println);
        System.out.println("--------------------------");

        //收集姓名到指定的数据结构
        LinkedHashSet<String> collect2 = employees.stream().map(Employee::getName)
                .collect(Collectors.toCollection(LinkedHashSet::new));
        collect2.forEach(System.out::println);

        //总数
        Long collect3 = employees.stream()
                .collect(Collectors.counting());
        System.out.println(collect3);
        System.out.println("-----------总数----------------------");

        //平均
        Double collect4 = employees.stream().collect(Collectors.averagingDouble(Employee::getSalary));
        System.out.println(collect4);
        System.out.println("------------平均-------------------");

        //总和
        Double collect5 = employees.stream().collect(Collectors.summingDouble(Employee::getSalary));
        System.out.println(collect5);
        System.out.println("--------总和---------------");

        //最大值
        Optional<Employee> collect6 = employees.stream().collect(Collectors.maxBy((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())));
        System.out.println(collect6.get().getSalary());
        System.out.println("----------最大值-------------");

//        进阶版
        System.out.println("进阶的战士");
        //单级分组
        Map<Integer, List<Employee>> collect7 = employees.stream().collect(Collectors.groupingBy(Employee::getAge));
        System.out.println(collect7);
        System.out.println("----------------------");

//        多级分组
        Map<Integer, Map<String, List<Employee>>> collect8 = employees.stream().collect(Collectors.groupingBy(Employee::getAge, Collectors.groupingBy(e -> {
            if (e.getAge() < 20)
                return "少年";
            else if (e.getAge() < 30)
                return "青年";
            else
                return "中年";
        })));
        System.out.println(collect8);
        System.out.println("----------------------");

        //分区--满足条件一个区,不满足另一个区
        Map<Boolean, List<Employee>> collect9 = employees.stream().collect(Collectors.partitioningBy(e -> e.getSalary() > 8000));
        System.out.println(collect9);
        System.out.println("-----------------------");

        //收集各种统计数据
        DoubleSummaryStatistics collect10 = employees.stream().collect(Collectors.summarizingDouble(Employee::getSalary));
        System.out.println(collect10+"-----------平均薪水"+collect10.getAverage());

        //连接字符串
        String collect11 = employees.stream().map(Employee::getName).collect(Collectors.joining(",", "-----", "-----"));
        System.out.println(collect11);
    }

}

集合类的应用之排序

package JDKNewFeature;

import Entity.Employee;

import java.util.Arrays;
import java.util.List;

/**
 * @ClassName StreamSimpleSort
 * @Description TODO
 * @Date 2018/7/30 15:08
 * @Version 1.0
 */
public class StreamSimpleSort {
    public static void main(String[] args){
        List<Employee> list = Arrays.asList(
                new Employee("张三", "上海", 5000, 22),
                new Employee("李四", "北京", 4000, 23),
                new Employee("c五", "日本", 6000, 50),
                new Employee("b七", "香港", 7000, 50),
                new Employee("赵六", "纽约", 1000, 8)
        );

//        list.stream()
//                .sorted()//自然排序
//                .forEach(System.out::println);

        System.out.println("------------------------------");
        list.stream()
                .sorted((e1,e2) -> {//定制排序
                    if(e1.getSalary() == e2.getSalary())
                        return e1.getName().compareTo(e2.getName());
                    else
                        return e1.getSalary() - e2.getSalary();
                }).forEach(e -> Employee.show(e));

    }
}

集合类的应用之Map操作

package JDKNewFeature;

import Entity.Employee;

import java.util.Arrays;
import java.util.List;

/**
 * @ClassName StreamSimpleV2
 * @Description TODO
 * @Date 2018/7/30 14:56
 * @Version 1.0
 */
public class StreamSimpleV2 {
    public static void main(String[] args){

        /** TODO
         * 映射
         * map -- 接受Lambda,将元素转换成其他形式或提取信息,接受一个函数作为参数,
         * 该函数会被应用到每个元素上,并将其映射成一个新的元素。
         *
         * flatmap -- 接受一个函数做为参数,将流中的每个值都转换成另一个流,然后将所有流连接成一个流,
         */
        List<Employee> list = Arrays.asList(
                new Employee("张三", "上海", 5000, 22),
                new Employee("李四", "北京", 4000, 23),
                new Employee("c五", "日本", 6000, 50),
                new Employee("b七", "香港", 7000, 50),
                new Employee("赵六", "纽约", 1000, 8)
        );
        //简单操作
        list.stream()
                .map(e -> e.name)//中间操作 映射
                .forEach(System.out::println);//终止流
    }
}

集合类的应用之flatMap

package JDKNewFeature;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

/**
 * @ClassName StreamSimpleV3
 * @Description TODO
 * @Date 2018/7/30 15:03
 * @Version 1.0
 */
public class StreamSimpleV3 {
    /**
     * 映射
     * map -- 接受Lambda,将元素转换成其他形式或提取信息,接受一个函数作为参数,
     * 该函数会被应用到每个元素上,并将其映射成一个新的元素。
     *
     * flatmap -- 接受一个函数做为参数,将流中的每个值都转换成另一个流,然后将所有流连接成一个流,
     */
    public static void main(String[] args){
        List<String> list = Arrays.asList("aaa","bbb","ccc","ddd");

        Stream<Stream<Character>> streamStream = list
                .stream()
                .map(StreamSimpleV3::getCharacter);//流中还是流

        streamStream.forEach(sm -> sm.forEach(System.out::println));

        System.out.println("-------------------------------------");
        list.stream()
                .flatMap(StreamSimpleV3::getCharacter)//大流中直接包含的是流元素,相当于add和addAll的区别。
                .forEach(System.out::println);
    }




    public static Stream<Character> getCharacter(String str){
        List<Character> list = new ArrayList<>();
        for (char c : str.toCharArray()) {
            list.add(c);
        }
        return list.stream();
    }
}

集合类的应用之并行

新建一个并行框架类
package JDKNewFeature;

import java.util.concurrent.RecursiveTask;

/**
 * @ClassName StreamParallel
 * @Description TODO  Stream API 可以声明性地通过parallel() 与sequential() 在并行流与顺序流之间进行切换。 Fork/Join框架
 * @Date 2018/7/31 14:48
 * @Version 1.0
 */
public class StreamParallel extends RecursiveTask<Long> {

    private long start;
    private long end;

    private static final long THRESHHOLD = 10000;

    public StreamParallel(long start, long end) {
        this.start = start;
        this.end = end;
    }

    @Override
    protected Long compute() {
        long length = end - start;

        if(length <= THRESHHOLD){
            long sum = 0;
            for (long i = start; i <= end; i++) {
                sum += i;
            }
            return sum;
        }else{
            long middle = (start + end) / 2;

            StreamParallel left = new StreamParallel(start, middle);
            left.fork();

            StreamParallel right = new StreamParallel(middle + 1, end);
            right.fork();

            return left.join()+right.join();
        }
    }
}

综合比较现有的集中方式计算效率

package JDKNewFeature;

import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.stream.LongStream;

/**
 * @ClassName Tester
 * @Description TODO 测试入口 JDK7的实现方式最优,stream并行流计算次之,普通的最次
 * @Date 2018/7/31 14:51
 * @Version 1.0
 */
public class Tester {
    public static void main(String[] args){
        parallelTest8();
        parallelTest();
        parallelTestPlain();
    }
//    并行流测试函数 JDK7
    public static void parallelTest(){
        Instant start = Instant.now();
        ForkJoinPool pool = new ForkJoinPool();
        ForkJoinTask<Long> task = new StreamParallel(0, 100000000L);

        Long sum = pool.invoke(task);
        Instant end = Instant.now();

        System.out.println("老年的迪斯科耗时:"+Duration.between(start,end).toMillis());
    }
//    jdk的实现方式
    private static void parallelTest8(){
        Instant start = Instant.now();

        long sum = LongStream.rangeClosed(0, 1000000000L)
                .parallel()//并行流
//                .sequential()//串行流
                .reduce(0, Long::sum);

        Instant end = Instant.now();

        System.out.println("摇滚的迪斯科耗时:"+Duration.between(start,end).toMillis());
    }
//    最普通的方式
    private static void parallelTestPlain(){
        Instant start = Instant.now();

        Long sum = 0L;
        for (int i = 0; i <= 100000000L; i++) {
            sum += i;
        }


        Instant end = Instant.now();
        System.out.println("普通的迪斯科耗时:"+Duration.between(start,end).toMillis());
    }
}

JDK1.8新特性之Optional

package JDKNewFeature;

import Entity.Employee;

import java.util.Optional;

/**
 * @ClassName OptionalSimple
 * @Description TODO OptionSimple类学习
 * @Date 2018/7/31 15:31
 * @Version 1.0
 */
public class OptionalSimple {

    /**
     * 常用方法:
     * Optional.of(T t) : 创建一个Optional 实例
     * Optional.empty() : 创建一个空的Optional 实例
     * Optional.ofNullable(T t):若t 不为null,创建Optional 实例,否则创建空实例
     * isPresent() : 判断是否包含值
     * orElse(T t) : 如果调用对象包含值,返回该值,否则返回t
     * orElseGet(Supplier s) :如果调用对象包含值,返回该值,否则返回s 获取的值
     * map(Function f): 如果有值对其处理,并返回处理后的Optional,否则返回Optional.empty()
     * flatMap(Function mapper):与map 类似,要求返回值必须是Optional
     */
    public static void main(String[] args) {
        ofTest();
        mapTest();
        orElseTest();
        ofnullableTest();
        flatMapTest();
        emptyTest();
    }

    //of 构建
    public static void ofTest() {
        Optional<Employee> op = Optional.of(new Employee());
        Employee employee = op.get();
        Employee.show(employee);

        //Optional<Object> op2 = Optional.of(null);//直接传null会发生空指针异常
//        Object o = op2.get();
//        System.out.println(o);
    }

    //    empty
    public static void emptyTest() {
        Optional<Object> op = Optional.empty();
        System.out.println(op.get());//也会报错,NoSuchElement.Exception
    }

    //ofnullable
    public static void ofnullableTest() {
        Optional<Object> op = Optional.ofNullable(null);
        if (op.isPresent())
            System.out.println(op.get());//仍然会报错,NoSUchELEMEnt.exception
        else
            System.out.println("No Value");
    }

    //ORelse
    //orElseGet
    public static void orElseTest(){
        Optional<Object> op = Optional.ofNullable(null);
        if(op.isPresent()){
            System.out.println(op.get());
        }else{
            op.orElse(new Employee());//如果没值,传入默认的值

            Object o = op.orElseGet(Employee::new);//函数式接口,可以写更多
            System.out.println(o);
        }
    }

    //map
    public static void mapTest(){
        Optional<Employee> op = Optional.ofNullable(new Employee("jim","shanghai",9000,55));
//        Optional<Employee> op = Optional.ofNullable(null);


        //有值返回map的操作,没值返回Optional.empty()
        Optional<Integer> salary = op.map(Employee::getSalary);
        System.out.println(salary.get());//如果传入为空,此时会报错

    }

    //flatMap
    public static void flatMapTest(){
//        Optional<Employee> op = Optional.ofNullable(new Employee("jim","shanghai",9000));
        Optional<Employee> op = Optional.ofNullable(null);
        //flatMap,返回的必须是Optional容器,进一步避免空指针异常
        Optional<Integer> optional = op.flatMap(e -> Optional.of(e.getSalary()));
        System.out.println(optional.orElse(10000));
    }
}

JDK1.8新特性之Predicate

package JDKNewFeature;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Predicate;

/**
 * @ClassName PredicateSimple
 * @Description TODO  Interface Predicate<T>  可以用作lambda表达式或方法引用的赋值对象
 * @Date 2018/7/30 10:49
 * @Version 1.0
 */
public class PredicateSimple {

    public static void main(String[] args) {
        System.out.println("普通战士");
        String name = "";
        String name1 = "12";
        String name2 = "12345";

        System.out.println(validInput(name, inputStr -> !inputStr.isEmpty() && inputStr.length() <= 3));
        System.out.println(validInput(name1, inputStr -> !inputStr.isEmpty() && inputStr.length() <= 3));
        System.out.println(validInput(name2, inputStr -> !inputStr.isEmpty() && inputStr.length() <= 3));
        System.out.println("进阶战士");
//        lambda
        Set<String> simple = new HashSet<>(Arrays.asList("love", "you", "like", "a song !"));

        simple.stream().forEach(e -> System.out.println(validInput(e, inputStr -> !inputStr.isEmpty() && inputStr.length() <= 3)));

        System.out.println("进阶战士--Equal");
        simple.stream().forEach(e -> System.out.println(Predicate.isEqual("love").or(Predicate.isEqual("you")).negate().test(e)));


    }

    public static boolean validInput(String name, Predicate<String> function) {
//        给定的参数上,评估谓词  !inputStr.isEmpty() &&  inputStr.length() <= 3
        return function.test(name);
    }


}

JDK1.8新特性之MapReduce

package JDKNewFeature;

import Entity.Employee;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;

/**
 * @ClassName MapReduce
 * @Description TODO  map和reduce的连接通常称为map-reduce模式,因google用它进行网络搜索而出名
 * @Date 2018/7/30 15:14
 * @Version 1.0
 */
public class MapReduce {
    public static void main(String[] args){
        /**
         * 终止操作:
         *
         * 归约
         * reduce(T identity, BinaryOperator) / reduce(BinaryOperator)
         *  -- 可以将流中的元素反复结合起来,得到一个值
         */

        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
        Integer reduce = list.stream().reduce(0, (x, y) -> x + y);
        System.out.println(reduce);
        List<Employee> employees = Arrays.asList(
                new Employee("张三", "上海", 5000, 22),
                new Employee("李四", "北京", 4000, 23),
                new Employee("c五", "日本", 6000, 50),
                new Employee("b七", "香港", 7000, 50),
                new Employee("赵六", "纽约", 1000, 8)
        );
        Optional<Integer> mapreduce = employees.stream()
                .map(Employee::getSalary)//现将salsry映射出来
                .reduce(Integer::sum);//进行归约求和
        System.out.println(mapreduce.get());

    }
}

JDK1.8新特性之通用类型

package JDKNewFeature;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

/**
 * @ClassName Genericty
 * @Description TODO  - <? extends T> 表示类型的上界,表示参数化类型的可能是T 或是 T的子类; <? super T> 表示类型下界(Java Core中叫超类型限定),表示参数化类型是此类型的超类型(父类型),直至Object;
 * @Date 2018/8/2 9:14
 * @Version 1.0
 */
public class Genericty {

    public  static void main(String[] args){
        List<? extends Father> list = new LinkedList<Son>();
        //        list.add(new Son()); 不能使用add方法
        Father father = list.get(0);//读取出来的东西只能存放在Father或它的基类里。
        Object object = list.get(0);//读取出来的东西只能存放在Father或它的基类里。
        Human human = list.get(0);//读取出来的东西只能存放在Father或它的基类里。
        Son son = (Son)list.get(0);


        //super只能添加Father和Father的子类,不能添加Father的父类,读取出来的东西只能存放在Object类里
        List<? super Father> list1 = new ArrayList<>();
        list1.add(new Father());
//        list1.add(new Human());//compile error
        list1.add(new Son());
//        Father person1 = list1.get(0);//compile error
//        Son son = list1.get(0);//compile error
        Object object1 = list1.get(0);
    }


}

class Human {
}

class Father extends Human {
}

class Son extends Father {
}

class LeiFeng extends Father {
}

猜你喜欢

转载自blog.csdn.net/Little_Red_Rose/article/details/81742164
今日推荐