小言_互联网的博客

Java一些特性的解析和示例 stream、Optional ... 最佳实践

376人阅读  评论(0)

本地变量类型推断:关键字 var (@since 10)

这个var跟C++11的auto一样的


//        1、本地类型推断 关键字 var @since 10
//        var 使用的是编译器的能力,通过赋值、变量定义时左值的类型来推断出变量的类型
//        var 定义的变量必须在声明时赋值,不然编译器也猜不透你想用的那个类型
        var var1_integer = 1;
        var var2_double = 2.00;
        var var3_string = "hello java11";
        var var4_list = new LinkedList<String>();
        var var5_complex = new HashMap<String, List<Double>>();

//        看一下所定义的变量类型
        System.out.println("############### var ################");
        System.out.println(var1_integer);
        System.out.println(var2_double);
        System.out.println(var3_string.getClass());
        System.out.println(var4_list.getClass());
        System.out.println(var5_complex.getClass());

//        Java 11 增强了lambda中的var的能力 @since 11
        IntFunction<Integer> addOperator = (var a) ->  a * a;

//        var 定义的变量与普通方式定义的变量是完全一样的
        var4_list.add("oracle");
        var4_list.add("java");
        var4_list.add("11");

        var tempList =  List.of(2.0, 3.0);
        var5_complex.put("keyone", tempList);

//      var 在循环中的使用
        for (var i = 0; i < var4_list.size(); i++) {
            System.out.println(var4_list.get(i));
        }

        for (var s : var4_list) {
            System.out.println(s);
        }

        for (var i = var4_list.iterator(); i.hasNext(); ) {
            System.out.println(i.next());
        }

        System.out.println(addOperator.apply(3));

        System.out.println("############### var ################");

输出

stream (@since 1.8 ) java 11 对其有增强

示例中要到的pojo


class Person implements Serializable{
    private String name;
    private String sex;
    private Integer age;

    public Person() {
    }

    public Person(String name, String sex, Integer age) {
        this.name = name;
        this.sex = sex;
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public Integer getAge() {
        return age;
    }

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

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                ", age=" + age +
                '}';
    }
//        2、stream @since 1.8
//        Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。
//        Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。
//        这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。
//        元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。
//        java 11 steam 有增强

        System.out.println("############### stream #############");

        //  使用steam将 List 转换为 Map
//        这里使用的 List.of @since 9 , 你可以把它理解为 初始化元素集合
        var personList = List.of(
                new Person("tom", "male", 35)
                , new Person("jary", "male", 34)
                , new Person("linda", "female", 23));

        var personMap = personList
                .stream()
                .collect(Collectors.toMap(Person::getName, i -> i));

//        forEach @since 1.8 这个应该不用多说了
        personMap.forEach((k,v)->{
            System.out.println("entry key : " + k + " value : "+v.toString());
        });

//      java stream wordcout example
//
        System.out.println("########## wordcount #####################");


//      Function 接收一个参数,返回一个参数 ;BiFunction 接收两个参数,返回一个参数;
//      java stream的出现使得我们对各种数据集合的复杂操作变得简单、明了
//      java stream 是java函数式编程支持的体现
//      而stream带来了对集合序列化操作的支持,整体看起来就像是链式模式的操作
//      stream相关的方法就像Apache Sparck,实际上每个方法的具体操作也跟spack差不多,当然肯定没有分布式的那些东西
//      我们来用stream完成一个Wordcount。
//      stream上的方法分为两类:中间操作 和 终端操作
//      对于操作的数据集来说使用中间操作的结果可以传递到下一步操作中
//      相反的终端操作则不会再产生中间结果集
//       我会对stream的比较复杂的方法进行说明,而那些见名知意的方法我想也不需要再次赘述了

//        limit 限流操作,比如数据流中有10个 我只要出前3个就可以使用。
//        distint 去重操作,对重复元素去重,底层使用了equals方法。
//        filter 过滤操作,把不想要的数据过滤。
//        peek 挑出操作,如果想对数据进行某些操作,如:读取、编辑修改等。
//        skip 跳过操作,跳过某些元素。
//
//        collect 收集操作,将所有数据收集起来,这个操作非常重要,官方的提供的Collectors 提供了非常多收集器,可以说Stream 的核心在于Collectors。
//        count 统计操作,统计最终的数据个数。
//        findFirst、findAny 查找操作,查找第一个、查找任何一个 返回的类型为Optional。
//        noneMatch、allMatch、anyMatch 匹配操作,数据流中是否存在符合条件的元素 返回值为bool 值。
//        min、max 最值操作,需要自定义比较器,返回数据流中最大最小的值。
//        reduce 规约操作,将整个数据流的值规约为一个值,count、min、max底层就是使用reduce。
//        forEach、forEachOrdered 遍历操作,这里就是对最终的数据进行消费了。
//        toArray 数组操作,将数据流的元素转换成数组。



        var wordinput = List.of("hello world", "hello apache", "oracle java" , "apache hadoop");

        wordinput.stream()
                .map(word->word.split("\\s"))
//                map 操作是对集合中的每个元素的操作 1对1
                .flatMap(Arrays::stream)
//                flatMap 操作是一种对数据扁平化的操作,是对集合中所有元素的操作
                .sorted()
//                这个就是排序了 , 在这个示例中可有可无
                .reduce(new HashMap<String, Integer>(),
                        new BiFunction<HashMap<String, Integer>, String, HashMap<String, Integer>>() {
                            @Override
                            public HashMap<String, Integer> apply(HashMap<String, Integer> stringIntegerHashMap, String s) {
                                if (stringIntegerHashMap.get(s) != null) {
                                    stringIntegerHashMap.put(s, stringIntegerHashMap.get(s) + 1);
                                    return stringIntegerHashMap;
                                }
                                stringIntegerHashMap.put(s, 1);
                                return stringIntegerHashMap;
                            }
                        },
                        new BinaryOperator<HashMap<String, Integer>>() {
                            @Override
                            public HashMap<String, Integer> apply(HashMap<String, Integer> stringIntegerHashMap, HashMap<String, Integer> stringIntegerHashMap2) {
                                return null;
                            }
                        })
//                reduce 是stream中比较复杂的一个操作,其含义是 合并 ,我们这个实现跟Hadoop MapReduce shuffle操作类似,
//                reduce 有3个重载
                .forEach( (k , v)->{
                    System.out.println("("+k+","+v+")");
                });
//        遍历,输出

        System.out.println("########## wordcount #####################");

输出

Optional (@since 1.8) java 11 对其有增强

Optional 是个容器:它可以保存类型T的值,或者仅仅保存null。Optional提供很多有用的方法,这样我们就不用显式进行空值检测。

Optional 类的引入很好的解决空指针异常。

    /**
     * 对可能返回null的函数和方法使用Optional返回值类型可大幅减少java.lang.NullPointerException异常的出现
     * @return
     */
    public Optional<Person> getPerson(){
        return Optional.ofNullable(new Person());
    }

      Person person = null;
        Person person1 = new Person("xiaoming" , "male" , 15);
//     Optional.of(obj).get() 这样跟直接用对象差不多,不推荐
        Person temp = Optional.of(person).get();
//        Optional.ofNullable 可以接受一个为null的对象
        if (Optional.ofNullable(person).isEmpty()) {
            System.out.println("object persion is null");
        }

//        Optional.of 接受一个null对象时会报异常:java.lang.NullPointerException
//        也就是说 of 接受的必须是一个非null对象才能执行后面的操作,这跟直接使用null对象几乎没有区别
        if (Optional.of(person).isEmpty()) {
            System.out.println("object persion is null");
        }
//		isEmpty 是判断一个对象是否为null
//		isPresent 判断的是一个对象是否有值
        if (Optional.ofNullable(person).isPresent()) {
            System.out.println("person is no value");

        }

//        Person temp = Optional.of(person).orElse(new Person("xiaohong", "famele", 14));

//        orElse 如果对象是一个null,那么会返回一个指定的同类型对象
        Person temp2 = Optional.ofNullable(person).orElse(new Person("xiaohong","famele",14));

        System.out.println(temp2.toString());

        Optional.ofNullable(person1).orElseGet(()-> new Person());

//        Optional.ofNullable(person).orElseThrow(()->new IllegalArgumentException("this object is null"));


//        Optional.ofNullable(person1).ifPresent();

        ComponentApplicationTests componentApplicationTests = new ComponentApplicationTests();

        Optional personOptional = componentApplicationTests.getPerson();

        if (personOptional.isEmpty()) {
            System.out.println("personOptional is null");
        }

        if (personOptional.isPresent()) {
            System.out.println("personOptional is no value");
        }

        Person personTemp = (Person)personOptional.orElseGet(() -> new Person("default", "male", 0));

        System.out.println(personTemp.toString());

try-with-resources(@since 1.7) 和 InputStream.transferTo (@since 9)

//        try-with-resources 的意义是 一但try-catch语句块中的代码出现异常,try()里的对象将被正确关闭。@since 1.7 更传统的方式是在finally里手动close。
        try(FileInputStream fileInputStream = new FileInputStream("D:/tmp/input.txt")){
//            InputStream.transferTo 方法直接将输入流中的数据传输到OutputStream
            fileInputStream.transferTo(new FileOutputStream("D:/tmp/inputCopy.txt"));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

输出


转载:https://blog.csdn.net/wangxudongx/article/details/104720317
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场