Java_day24

类型推断:你还可以进一步简化你的代码
   Java编译器会从上下文(目标类型)推断出用什么函数式接口来配合Lambda表达式,这意味着它也可以推断出适合Lambda的签名,因为函数描述符可以通过目标类型来得到。这样做的好处在于,编译器可以了解Lambda表达式的参数类型,这样就可以在Lambda语法中省去标注参数类型。
    

lambda表达式:
   方法引用: 简化lambda,重复利用已有的代码

    方法引用让你可以重复使用现有的方法定义,并像Lambda一样传递它们。
    方法引用可以被看作仅仅调用  【特定方法的Lambda】 的一种快捷写法。
    当你需要使用方法引用时,目标引用放在分隔符::前,方法的名称放在后面。
    
    1.引用构造器
        Supplier<类名> 变量名 = 类名::new
        Student stu = 变量名.get();

    2.引用有参数构造器
        BiFunction<参数1, 参数2, 类名>  bf = 类名::new;
        类名 变量名 = bf.apply(值1,值2);

    3.引用数组构造器
        IntFunction<int[]> arrayMaker = int[]::new;
        int[] array = arrayMaker.apply(10);

    4.引用静态方法
        函数接口类型 变量名 = 类名::静态方法名

    5.普通方法的引用:
        函数接口类型 变量名 = 对象::方法名;
    
    6.实例方法引用

        类名::方法名A;
        将lambda的参数 直接当做 A方法的参数
        

        //这种写法,不讨论返回值的问题。有就自动返回。
        //1.如果lambda的参数正好和::后面方法A的参数一样
        //那么就是调用::后面的方法A,把lambda的参数传进去
            // R apply(T t);
        Consumer<String> f = System.out::println;
        Consumer<String> f1 = (t)->{System.out.println(t);};
        
        // void accept(T t, U u);
        BiConsumer<Integer,Integer> bc = (a,b)->{Math.max(a, b);};
        BiConsumer<Integer,Integer> bc1 =  Math::max;
        
    
        //2.如果lambda的参数 比::后面方法A的参数多
        //那么就是第一个参数调用::后面方法A,把lambda剩下的参数传入::后面的方法A
        // R apply(T t);
        Function<String,String> fun1 = String::toUpperCase;
        Function<String,String> fun = (t)->t.toUpperCase();
        
        // void accept(T t, U u);
        BiConsumer<String,Integer> bc = String::substring;
        BiConsumer<String,Integer> bc1 = (a,b)->{a.substring(b);};


Optional类 : 可选择的

    作用:防止NullPointerException异常的辅助类型
    取值:null 或者 不是null

    Optional 被定义为一个简单的容器,其值可能是null或者不是null。在Java8之前一般某个函数应该返回非空对象但是偶尔却可能返回了null,而在Java 8中,不推荐你返回null而是返回Optional。
    这是一个可以为null的容器对象。
    
    如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。
    
Optional的使用:
  1.创建Optional:
    1.Optional.of(值);                 为非null的值创建一个Optional,如果这个值为null报错
    2.Optional.ofNullable(值);   为值创建一个Optional,如果值为null,则返回一个空的Optional
        代码:Optional.ofNullable(null);
        返回结果 :  Optional.empty
  2.使用:

      1.isPresent();   如果值不为空返回true,否则返回false  
      2.get();   如果有一个值,返回值,否则抛出 NoSuchElementException 
      3.ifPresent(Consumer<? super T> consumer)  如果存在值,则使用该值调用指定的消费者,否则不执行任何操作。 
         Optional<String> o1 = Optional.of("tom");
         Optional<String> o2 = Optional.ofNullable(null);
         o1.ifPresent(System.out::println);
         o2.ifPresent(System.out::println);//不执行
     4.orElse(T other);     值如果存在返回值,否则返回 other 。
         System.out.println(o1.orElse("aaa"));//o1,不为null返回原值
         System.out.println(o2.orElse("aaa"));//o2,为null 返回aaa
     5.orElseGet(Supplier<? extends T> other) 
         返回值(如果存在),否则调用 other并返回该调用的结果。
         将操作的结果当做other值
     6.orElseThrow(Supplier<? extends X> exceptionSupplier) 
         返回包含的值(如果存在),否则抛出由提供的供应商创建的异常。
     7.map(Function<? super T,? extends U> mapper) 
         如果存在一个值,则应用提供的处理函数,如果结果不为空,则返回一个 Optional结果的 Optional 。为null抛异常 
         Optional<Integer> map = o1.map(str->1);
         System.out.println(map.get());
     8.flatMap(Function<? super T,Optional<U>> mapper) 
         如果一个值存在,应用提供的 Optional映射函数给它,返回该结果,否则返回一个空的 Optional 。 
         Optional<String> o3 = o1.flatMap(a->Optional.of("10"));
         System.out.println(o3.get());
     区别 :  flatMap中的mapper返回值必须是Optional;flatMap不会对返回值自动封装为Optional类型
     9.filter(Predicate<? super T> predicate) 
         如果一个值存在,并且该值给定的断言相匹配时,返回一个 Optional描述的值,否则返回一个空的 Optional 。        
         Optional<String> filter = o1.filter(str->str.length()<2);
         System.out.println(filter);


Stream : 流水线
    
    流水线 : 对数据的一组操作
    jdk8,添加了新的类java.util.Stream:

  1. Java8中的Stream是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利高效的聚合操作,或者大批量数据操作
  2. Stream的API结合Lambda表达式,极大的提高编程效率和程序可读性
  3. 同时它提供串行和并行两种模式进行操作

    
流操作
    java.util.stream.Stream中的Stream接口定义了许多操作。
    它们可以分为两大类。
        1.中间操作 : 可以连接起来的流操作
        2.终端操作 : 关闭流的操作
            终端操作会从流的流水线生成结果。
            其结果是任何不是流的值,比如List<Integer>,甚至void。
        注:除非流水线上触发一个终端操作,否则中间操作不会执行任何处理。使用流
    流的使用一般包括三件事:
    1.一个数据源(如集合)来执行一组操作;
    2.一个中间操作链,形成一条流的流水线;
    3.一个终端操作,执行流水线,并能生成结果。

    4.Stream对象的构建:

        1.使用值构建
        Stream<String> stream = Stream.of("a", "b", "c");
        2. 使用数组构建
        String[] strArray = new String[] {"a", "b", "c"};
        Stream<String> stream = Stream.of(strArray);
        Stream<String> stream = Arrays.stream(strArray);
        3. 利用集合构建(不支持Map集合)
        List<String> list = Arrays.asList(strArray);
        stream = list.stream();
        注:基本数据类型的流:IntStream ,LongStream,DoubleStream
            不要选用Stream<Integer>,Stream<Long>,Stream<Double>因为自动装箱耗时,效率低
           Java 8 中还没有提供其它基本类型数值的Stream
        4.IntStream:数值Stream的构建:
        IntStream s1 = IntStream.of(new int[]{1, 2, 3});
        //[1,3)
        IntStream s2 = IntStream.range(1, 3);
        //[1,3]
        IntStream s3 = IntStream.rangeClosed(1, 3);

Stream转换为其它类型:
    Stream<String> stream = Stream.of("hello","world","tom");
    1.转换为Array
        String[] strArray  = stream.toArray(String[]::new);
    2.转换为Collection
        List<String> list1 = stream.collect(Collectors.toList());
        List<String> list2 = stream.collect(Collectors.toCollection(ArrayList::new));
        Set<String> set3 = stream.collect(Collectors.toSet());
        Set<String> set4 = stream.collect(Collectors.toCollection(HashSet::new));
    3.转换为String
        String str = stream.collect(Collectors.joining()).toString();

    注意 : 一个 Stream 只可以使用一次,上面的代码为了简洁而重复使用了多次。
        这个代码直接运行会抛出异常的:
        java.lang.IllegalStateException: stream has already been operated upon or closed流操作
    中间操作 : Intermediate
 

       1.map:映射
            map(Function<? super T,? extends R> mapper);  返回由给定函数应用于此流的元素的结果组成的流。     
            eg:把 Stream中 的每一个元素,映射成另外一个元素
            public static void main(String[] args) throws Exception {
                Stream<String> stream = Stream.of("tom","lisi","wangwu");
                //R apply(T t);
                Function<String,String> fun = (t)->t.toUpperCase();
                List<String> list = stream.map(fun).collect(Collectors.toList());
                System.out.println(list);
            }
        
       2. filter:过滤
            filter(Predicate<? super T> predicate); 返回由与此给定谓词匹配的此流的元素组成的流。

            eg:获取字符串中长度大于3的字符串
             public static void main(String[] args) throws Exception {
                Stream<String> stream = Stream.of("tom","lisi","wangwu","a");
                List<String> list = stream.filter((msg)->msg.length()>3).collect(Collectors.toList());
                // boolean test(T t);
                // Predicate<T>
                System.out.println(list);
            }  
        
       3.peek : 偷看,可以用来检查流当前的状态。
            (Consumer<? super T> action); 对每个元素执行操作并返回一个新的 Stream
            注意:调用peek之后,一定要有一个最终操作
            public static void main(String[] args) throws Exception {
                Stream<String> stream = Stream.of("tom","lisi","wangwu");
                stream.filter(e -> e.length() > 3).peek(e -> System.out.println("符合条件的值为: " + e)) .collect(Collectors.toList());
            }

        4.distinct:去重;返回由不同元素组成的流
        5.sorted; 返回由此流的元素组成的流,根据自然顺序排序。
           sorted(Comparator<? super T> comparator) 返回由此流的元素组成的流,根据自然顺序排序。
        6.limit    
            limit(long maxSize);限制流的长度不超过maxSize。

            public static void main(String[] args) throws Exception {
                Stream<String> stream = Stream.of("tom","lisi","wangwu","hhhhhh","werwerwefwe");
                stream.filter(e -> e.length() > 3)
                      .peek(e -> System.out.println("符合条件的值为: " + e)).limit(2)
                      .collect(Collectors.toList());
            }
            满足条件的有多个,但是最终返回的集合中只有两个数据。
        7.skip: skip(long n); 跳过多少个元素
                public static void main(String[] args) throws Exception {
                    Stream<String> st = Stream.of("tom","lisi","wangwu","zhaoliu");
                    List<String> list = st.skip(2).collect(Collectors.toList());
                    System.out.println(list);
                }
            最终打印[wangwu, zhaoliu]

        parallel  :  并行 
        sequential : 有顺序

    终端操作 : Terminal
        1.forEach 
            遍历 接收一个 Lambda 表达式,然后在 Stream 的每一个元素上执行该表达式。
            stream.forEach(System.out::println);
        2.findFirst 
            总是返回 Stream 的第一个元素,或者空,返回值类型:Optional。
            如果集中什么都没有,那么list.stream().findFirst()返回一个Optional<String>对象,但是里面封装的是一个null。
            
            public static void main(String[] args) throws Exception {
                Stream<String> stream = Stream.of("hello","world","tom");
                Optional<String> findFirst = stream.findFirst();
                System.out.println(findFirst);
            }
        
        3.anyMatch 
            allMatch(Predicate<? super T> predicate) 
            任意一个匹配成功返回true
       4.allMatch
            allMatch(Predicate<? super T> predicate) 
            所有匹配成功才返回true
        5.noneMatch 
            noneMatch(Predicate<? super T> predicate)
            没有一个匹配的就返回true 否则返回false
        
        6.count 计数
            返回Stream中元素的个数,返回值类型是long。


        7.reduce 合并
            允许通过指定的函数来将stream中的多个元素规约合并为一个元素.
            
            它提供一个起始值(种子),然后依照运算规则(BinaryOperator),和前面 Stream 的第一个、第二个、第 n 个元素组合。从这个意义上说,字符串拼接、数值的 sum、min、max等都是特殊的 reduce。
            
          

  eg1:
                1-10累加
                IntStream red = IntStream.range(1, 10);
                Integer sum = red.reduce(0, (a, b) -> a+b);
                System.out.println(sum);
            eg2:
                拼接字符串
                String concat = Stream.of("A", "B", "C", "D").reduce("", String::concat);
                System.out.println(concat);
            eg3:
                List<String> list = Arrays.asList("test","javac","hello","world","java","tom","C","javascript");
                Optional<String> reduce = list.stream().sorted((s1,s2)->s2.length()-s1.length()).filter(s->s.startsWith("j")).map(s->s+"_briup").reduce((s1,s2)->s1+"|"+s2);
                System.out.println(reduce.orElse("值为空"));


        
        8.max:
            max(Comparator<? super T> comparator) 
            根据提供的 Comparator返回此流的最大元素。 
            String[] arr= {"zom","lisi","wagnwu"};
            Stream<String> stream = Arrays.stream(arr);
            Optional<String> max = stream.max(String::compareTo);
            System.out.println(max.get());//zom
        9.min:
            min(Comparator<? super T> comparator) 
            根据提供的 Comparator返回此流的最小元素。 
            
            String[] arr= {"zom","lisi","wagnwu"};
            Stream<String> stream = Arrays.stream(arr);
            Optional<String> max = stream.min(String::compareTo);
            System.out.println(max.get());//lisi

        10.forEachOrdered
            如果流具有定义的遇到顺序,则以流的遇到顺序对该流的每个元素执行操作。 
            Stream<String> stream = Stream.of("tom","lisi");
            stream.forEachOrdered((a)->{System.out.println(a);});

       11.toArray 
            toArray(IntFunction<A[]> generator) 
            使用提供的 generator函数返回一个包含此流的元素的数组,以分配返回的数组,以及分区执行或调整大小可能需要的任何其他数组。 
            Stream<String> stream = Stream.of("tom","lisi");
            String[] array = stream.toArray(String[]::new);
        12.collect 
            collect(Collector<? super T,A,R> collector) 
            使用 Collector对此流的元素执行 mutable reduction Collector 。  
            
            Stream<String> stream = Stream.of("tom","lisi");
            List<String> list = stream.collect(Collectors.toList());
            Set<String> set = stream.collect(Collectors.toSet());
        13.findAny
            返回描述流的一些元素的Optional如果流为空,则返回一个空的Optional 
        14.iterator
            获得迭代器

    短路操作 : Short-circuiting: 
        anyMatch
        allMatch
        noneMatch
        findFirst
        findAny 
        limit

Stream.generate
    自己来控制Stream的生成
    这种情形通常用于随机数、常量的 Stream,或者需要前后元素间维持着某种状态信息的 Stream。
    把 Supplier 实例传递给 Stream.generate() 生成的 Stream,由于它是无限的,在管道中,必须利用limit之类的操作限制Stream大小。
    可以使用此方式制造出海量的测试数据

    eg:
        生成100个随机数并由此创建出Stream实例
        Stream.generate(()->(int)(Math.random()*100)).limit(100).forEach(System.out::println);

工具类:Collectors 
    java.util.stream.Collectors 类
    主要作用就是辅助进行各类有用的操作。

    eg1:
        把Stream中的元素进行过滤然后再转为List集合
        List<String> list = Arrays.asList("test","hello","world","java","tom","C","javascript");
        List<String> result = list.stream().filter(s->s.length()>4).collect(Collectors.toList());


串行和并行
    串行Stream上的操作是在一个线程中依次完成
    并行Stream则是在多个线程上同时执行
        
串行和并行的相互转换:

    可以通过对收集源调用parallelStream方法来把集合转换为并行流。
    对顺序流调用parallel方法把流转换成并行流。

    并行流就是一个把内容分成多个数据块,并用不同的线程分别处理每个数据块的流。

    对顺序流调用parallel方法并不意味着流本身有任何实际的变化。它在内部实际上就是设了一个boolean标志,表示你想让调用parallel之后进行的所有操作都并行执行。
    只需要对并行流调用BaseStream下的sequential()方法就可以把它变成顺序流。
    

  并行测试:
    public static void main(String[] args) {
       //生成100万个不同的字符串放到集合中
       int max = 1000000;
       List<String> values = new ArrayList<String>(max);
       for (int i = 0; i < max; i++) {
           UUID uuid = UUID.randomUUID();
           values.add(uuid.toString());
       }
       //1纳秒*10^9=1秒 
       long t0 = System.nanoTime();
       //串行stream 
       long count = values.stream().sorted().count();
       //并行stream
       //long count = values.parallelStream().sorted().count();
       long t1 = System.nanoTime();
       
       long time = t1 - t0;
       System.out.println(count);
       System.out.println(time);
    }

Map集合: HashMap
    
    Map类型不支持stream
    Java8为Map新增的方法
        
       基础数据:
        Map<String, Integer> map = new HashMap<>();
        map.put("tom",1);
        map.put("lisi",2);
        map.put("wangwu",3);
        map.put("zhaoliu",4);
        map.put("zhangsan",null);

    1.Object compute(Object key, BiFunction remappingFunction):
        该方法使用remappingFunction根据原key-value对计算一个新的value。
        只要新的value不为null,就使用新的value覆盖原value;
        如果新的value为null,则删除原key-value对;      
        // BiFunction<? super K, ? super V, ? extends V>
        //  R apply(T t, U u);
        BiFunction<String, Integer, Integer> bif = (key,value)->{
            return 20;
        };
        map.compute("tom", bif);//替换tom的值
        map.compute("lisi", (key,value)->33);//替换lisi的值

    2.Object computeIfAbsent(Object key, Function mappingFunction):
        如果传入的key参数在Map中对应的value为null,该方法将使用mappingFunction根据原key、value计算一个新的结果,
 则用该计算结果覆盖原value;
        如果传入的key参数在Map中对应的value不为null,则该方法不做任何事情;
        如果原Map原来不包括该key,该方法可能会添加一组key-value对。 

    3.Object computeIfPresent(Object key, BiFunction remappingFunction):
        并且该计算结果不为null,则使用该结果覆盖原来的value;
        
        //R apply(T t, U u);
        map.computeIfPresent("zhaoliu", (key,value)->10);
        System.out.println(map);
    
    4.void forEach(BiConsumer action):
        该方法是Java8为Map新增的一个遍历key-value对的方法。
        
        map.forEach((key,value)->{
            System.out.println(key+"--"+value);
        });

    5.Object getOrDefault(Object key, V defaultValue):
        获取指定的key对应的value。如果该key不存在,则返回defaultValue。
        
        System.out.println(map.getOrDefault("zhaoliu", 10));//4
        System.out.println(map.getOrDefault("a", 10));//10

    6.Object merge(Object key, Object value, BiFunction remappingFunction):
        该方法会先根据key参数获取该Map中对应的value。
        如果获取的value为null,则直接使用传入的value覆盖原value。
        如果获取的value不为null,则使用remappingFunction函数根据原value、新value计算一个新的结果,并用新的结果去覆盖原有的value。
        
        key对应的value为null:
            map.merge("zhangsan", 20, (key,value)->{return value+1;});
            System.out.println(map);
            //zhangsan=20

        key对应的value不为null:
            map.merge("zhaoliu", 20, (key,value)->{return value+1;});
            System.out.println(map);
            //{zhaoliu=21}

    7.Object putIfAbsent(Object key, Object value):
        该方法会自动检测指定的key对应的value是否为null,
        如果该key对应的value为null,则使用传入的新value代替原来的null。
        如果该key对应的value不是null,那么该方法不做任何事情。
        
        key对应value为null:
            map.putIfAbsent("zhangsan", 20);
            System.out.println(map);
            //zhangsan=20

        key对应value不为null:
            map.putIfAbsent("wangwu", 20);
            System.out.println(map);
            //wangwu=3
                
    8.Object replace(Object key, Object value):
        将Map中指定key对应的value替换成新value并把被替换掉的旧值返回。
        如果key在Map中不存在,该方法不会添加key-value对,而是返回null。
        
        map.replace("lisi", 42);
        System.out.println(map);
        //lisi=42

    9.Boolean replace(K key, V oldValue, V newValue):
        将Map中指定的key-value对的原value替换成新value。
        如果在Map中找到指定的key-value对,则执行替换并返回true,否则返回false。
        
        key-value都正确
            map.replace("lisi", 2, 23);
            System.out.println(map);
            //lisi=23//替换成功
        key-value没有都正确
            map.replace("lisi", 21, 23);
            System.out.println(map);
            //lisi=2//替换失败

    10.replaceAll(BiFunction function):
        该方法使用function对原key-value对执行计算,
        并将计算结果作为key-value对的value值

        map.replaceAll((key,value)->{return value!=null?value+1:0;});
        System.out.println(map);
        {lisi=3, tom=2, zhaoliu=5, zhangsan=0, wangwu=4}


Date:
    最原始:注:本次用到的Date都是java.util.Date
       1.创建时间
        //当前时间
        java.util.Date d  = new java.util.Date();
        //某个时间戳创建时间
        //时间戳 : 1970-01-01到某个日期的毫秒数
        java.util.Date d1 = new  java.util.Date(12310231231L);

       2.将字符串解析为时间Date类型
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        String msg = "2019-8-28 7:41:07";
        Date parse = sdf.parse(msg);
        System.out.println(parse.toLocaleString());

       3.将日期Date类型格式化为字符串:
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        String format = sdf.format(new Date());
        System.out.println(format);
    
    新:提供了java.time包下的类处理日期
        java.time – 包含值对象的基础包
        java.time.chrono – 提供对不同的日历系统的访问
        java.time.format – 格式化和解析时间和日期
        java.time.temporal – 包括底层框架和扩展特性
        java.time.zone – 包含时区支持的类            
       新增:
        创建日期:
            //创建指定时间
            LocalDate date = LocalDate.of(2019, Month.OCTOBER, 28);
            System.out.println(date.toString());

            //创建当前时间
            LocalDateTime now = LocalDateTime.now();
            
            //创建指定时间
            LocalDateTime ldt = LocalDateTime.of(2019, 8, 28, 7, 49, 28);
            System.out.println(ldt.toString());
        
        格式化日期:
           将字符串转换为日期
     

       DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            String time= "2019-08-28";
            LocalDate dl1 = LocalDate.parse(time, dtf);
            String str1 = dl1.format(dtf);
            System.out.println(str1);
           


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值