JDK1.8新特性

来源:互联网 发布:台湾文献数据库 编辑:程序博客网 时间:2024/05/21 06:32
  • javac -source 1.7 -target 1.8 T.java 表示源文件版本为1.7,编译成的字节码使用1.8

  • lambda表达式,即由用户来提供行为的具体实现.

/** * @author Sunset *         Created on 2016/05/15. */public class T {    public static void main(String[] args) {        /**         * lambda语法,提供的是相应函数式接口的目标方法实现,并根据该实现创建一个接口的对象。         * 关于该目标方法的具体参数值,lambda表达式并不提供!!!!         * lambda表达式的标准写法为 (arg1,arg2) -> {statements;}         * 对于只有一个参数可以写为 arg -> {statements}         * 对于只有一条返回语句的实现可以写为 arg -> arg + "sss",其自动加return         */        act(new Person("love"),p -> System.out.println(p.getName()));        // ClassName::method方法引用。        // 可以看做lambda表达式的一个特殊用法,该语法在stream的map、groupingBy等方法中特别有用。        // 其等价于classInstance -> classInstance.method()或        // classInstance -> {classInstance.method();}        // classInstance为ClassName类型的对应参数,并根据目标函数是否有返回值决定不同的调用方式。        // 以下等价于act(new Person("fff"),p -> p.getName());        act(new Person("fff"),Person::getName);    }    public static void act(Person p,MyLambda ml){        ml.sayHello();        ml.doSomthing(p);        ml.sayGoodBye();    }}/** * 支持函数式接口的接口可以使用lambda表达式 */@FunctionalInterfaceinterface MyLambda{    //必须刚好提供一个目标方法(无default),lambda表达式将实际传入该方法,并创建对象,使用@FunctionalInterface进行约束.    void doSomthing(Person s);    default void sayHello(){        System.out.println("hello");    }    default void sayGoodBye(){        System.out.println("GoodBye");    }}class Person{    private String name;    public Person(String name) {        this.name = name;    }    public String getName() {        return name;    }    public Person setName(String name) {        this.name = name;        return this;    }}
  • Stream类,它提供了类似于python中generator的概念,即只保存算法的一个类。是一个高版本的iterator。
//优势,可以提供自动并行化处理,可以产生无限元素。/**  *可以由以下几种方式产生  *Collection.stream()  *静态方法LongStream.of(1,2,3,4);  *自定义**//**  *流操作分为两种类型:  *Intermediate:一个流后面可一个跟多个Intermediate操作,其作用是打开流,对其数据进行某种程度的映射,并返回一个新流。  *该类操作都是lazy的,只有在terminal方法触发后,才开始遍历元素,也就是仅仅调用该类方法只是将操作放到stream的操作序  *列中,等到调用terminal时再对每一个元素调用执行。该类操作有,  *map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered  *terminal,将流中的每一个元素读出,并操作,一个流最多只能有一个terminal操作,且必须为最后一个操作。  *该类操作有forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、   *noneMatch、 findFirst、 findAny、 iterator**/import java.util.List;import java.util.Map;import java.util.Random;import java.util.function.Function;import java.util.function.Supplier;import java.util.stream.Collectors;import java.util.stream.Stream;/** * @author Sunset *         Created on 2016/05/15. */public class T {    public static void main(String[] args) {        /**         * -*- Intermiate方法 -*-         *filter过滤,接收一个Predicate         * map将每一个元素进行 1<->1 映射并返回新元素(可以返回不同的类型),接收一个Function         * flatmap,将一个元素进行1 -> *映射,多端结果用一个Stream保存         * peek获得每一个元素,不能改变元素,接收一个Consumer         * distinct去除重复元素         *         * limit(n)表示取前n個元素,skip(n)表示跳過前n個元素,這將#導致该操作前面#         * Intermediate操作所對應的元素數量減少。除非前面有sorted操作(不知道排序后的顺序,无法应用short-cut)         * eg:len(s) == 10,s.peek().sorted().peek().limit(5),则第一个peek以及sorted处理的元素个数为10,         * 第二个peek处理的元素个数为5         *         * -*- Terminal方法 -*-         * collect方法将其作为了个Collection返回         *         * reduce(start,Function),使用start作为初始种子,两两进行reduce操作         * min,max,sum,findFirst,findAny,count,forEach,forEachOrdered         * findFirst/findAny也是一个short-cut操作,可能skip后面的元素         *         * 以下三个Match方法并不一定遍历所有元素,只要足够返回条件,则skip剩余元素。         * allMatch,判断是否全部符合         * anyMatch,有一个符合即可         * noneMatch,无符合         *         **/        Stream<String> stringStream = Stream.of("a", "b", "c", "a");        //此时由于都是Intermediate操作所以并不执行,所以peek操作不会打印        Stream<Integer> ins = stringStream.filter(x -> x != null).map(x -> x.hashCode()).distinct().peek(x -> System.out.println(x));        //此时调用了一个terminal方法,所以前面的Intermediate操作也被执行,所以peek打印hash值        //anyMatch有skip功能,所以上面的peek不是打印全部元素。        ins.anyMatch(x -> x == 98);        /**         * 自定义生成流,先实现Supplier接口,然后调用Stream.generate()来生成         * 以下生成一个等差数列         */        Stream<Integer> dc = Stream.generate(new Supplier<Integer>() {            int x = 0;            @Override            public Integer get() {                x += 3;                return x;            }        });        //不是一个并行流返回false        System.out.println(dc.isParallel());        //count用于终结触发前面的中间方法。        dc.limit(4).peek(x -> System.out.println(x)).count();        /**         * Collectors提供了很多有用的reduction方法,可以将stream通过collect转成集合         * Person::getAge为lambda表达式的特殊用法,等价于 person -> person.getAge()         */        Map<Integer, List<Person>> personGroups = Stream.generate(new PersonSupplier()).                limit(100).                collect(Collectors.groupingBy(Person::getAge));        System.out.println(personGroups);        System.out.println();    }}class Person{    private int age;    private String name;    public int getAge() {        return age;    }    public String getName() {        return name;    }    public Person setName(String name) {        this.name = name;        return this;    }    public Person setAge(int age) {        this.age = age;        return this;    }}class PersonSupplier implements Supplier<Person>{    private Random random = new Random();    @Override    public Person get() {        Person p = new Person();        p.setAge(random.nextInt(20));        p.setName("sss");        return p;    }}//再看reduce系列方法1. Optional reduce(BinaryOperator<T> bo);该方法在stream元素为空时,返回Optional.EMPTY,在元素个数为一时直接将该元素添加到Optional中,否则进行reduce操作,初始选择头两个元素,然后以两个元素的reduce结果作为下一次reduce的第一个元素,进行下一次reduce操作。实际流程类似下方:          boolean foundAny = false;          T result = null;          for (T element : this stream) {              if (!foundAny) {                  foundAny = true;                  result = element;              }              else                  result = accumulator.apply(result, element);          }          return foundAny ? Optional.of(result) : Optional.empty();2. T reduce(T identity,BinaryOperator<T> bo);该方法可以直接返回T,而不是一个Optional,因为提供了第一个元素identity,所以不会返回空结果,其余规则与一相同。3.<R, A> R collect(Collector<? super T, A, R> collector);可以注意到一二两个reduce操作,其要求每次reduce操作的结果(中间结果)以及最终返回结果都与T一致,所以系统提供一个灵活的collect方法。其中R表示最终返回结果,A表示中间结果。 Collector接口的方法如下 //该方法返回一个Supplier对象(可用lambda),该对象用于提供一个中间结果,会用于实际reduce Supplier<A> supplier() //用于执行实际的reduce操作 BiConsumer<A, T> accumulator() //将中间结果转换为返回结果类型 Function<A, R> finisher() //用于标识流类型,Characteristics.CONCURRENT/UNORDERED有且只有一个在集合中。 Set<Characteristics> characteristics() //暂时忽略 BinaryOperator<T> combiner() collect的实际工作流程如下 1)调用collector.supplier().get()返回一个中间结果类型对象a。 2)对每个元素e调用collector.accumulator.accept(a,e)进行reduce操作,该调用每次都是用第一步产生的a,返回值是void,这意味着a是一个可变对象reduce操作才有意义。 3)调用collector.finisher().apply(a)返回真正的结果对象。4.Collectors提供了许多方法可以快速生成Collector对象。总结如下:groupingBypartitionBytoListtoMaptoSettoConcurrentMapaverageing*summing*summarizing*//最终返回统计对象,可以获得avg/sum/min等数据joining//连接元素一个小demo,计算九个字符串的hashcode加和/** * @author Sunset *         Created on 2016/07/29. */public class X {    public static void main(String[] args) {        List<List<String>> lists = new ArrayList<>();        List<String> l1 = new ArrayList<>();        l1.add("l1_1");        l1.add("l1_2");        l1.add("l1_3");        List<String> l2 = new ArrayList<>();        l1.add("l2_1");        l1.add("l2_2");        l1.add("l2_3");        List<String> l3 = new ArrayList<>();        l1.add("l3_1");        l1.add("l3_2");        l1.add("l3_3");        lists.add(l1);        lists.add(l2);        lists.add(l3);        Integer i = lists.stream().flatMap(Collection::stream).collect(new Collector<String, IntegerHoler, Integer>() {            @Override            public Supplier<IntegerHoler> supplier() {                return IntegerHoler::new;            }            @Override            public BiConsumer<IntegerHoler, String> accumulator() {                return (ih,s) -> ih.setI(ih.getI()+s.hashCode());            }            @Override            public BinaryOperator<IntegerHoler> combiner() {                return null;            }            @Override            public Function<IntegerHoler, Integer> finisher() {                return IntegerHoler::getI;            }            @Override            public Set<Characteristics> characteristics() {                Set<Characteristics> ss = new HashSet<Characteristics>();                ss.add(Characteristics.CONCURRENT);                return ss;            }        });        System.out.println(i);    }}class IntegerHoler{    private Integer i = new Integer(0);    public Integer getI() {        return i;    }    public IntegerHoler setI(Integer i) {        this.i = i;        return this;    }
1 0