JAVA8 新特性

1. java 新特性介绍

1.1. 主要新特性

  1. Lambda 表达式: Lambda允许把函数作为一个方法的参数(函数作为参数传递进方法中)。
  2. 方法引用 : 方法引用提供了非常有用的语法,可以直接引用已有Java类或对象(实例)的方法或构造器。与lambda联合使用,方法引用可以使语言的构造更紧凑简洁,减少冗余代码。
  3. 默认方法 :默认方法就是一个在接口里面有了一个实现的方法。
  4. 1. Nashorn, JavaScr新工具 :新的编译工具,如:Nashorn引擎 jjs、 类依赖分析器jdeps。
  5. Stream API −新添加的Stream API(java.util.stream) 把真正的函数式编程风格引入到Java中。
  6. Date Time API :加强对日期与时间的处理。
  7. Optional 类 : Optional 类已经成为 Java 8 类库的一部分,用来解决空指针异常。
  8. ipt 引擎 : Java 8提供了一个新的Nashorn javascript引擎,它允许我们在JVM上运行特定的javascript应用

2. 接口的默认、静态方法

2.1. java8以前的接口

在java8之前Java 中接口里面的方法默认都是 public abstract 修饰的抽象方法并且没有方法体

2.2. 接口中的 static 方法

  1. 使用 static 修饰接口中的方法, 必须有主体。
  2. 接口中的 static方法 只能被 接口本身调用:接口名.方法名(...)。
public interface InterfaceText {
    void walk();

    static void testStatic(){
        System.out.println("接口中的静态");
    }
}

class IterfaceTestClass{
    public static void main(String[] args) {
        InterfaceText.testStatic();
    }
}
  1. 接口中的 static方法,不能被 子接口继承。
  2. 接口中的 static 方法,不能被 实现类 重写 及调用。

2.3. 接口中的 default 方法

在接口中可定义一个使用default修饰有方法体的方法,接口中可以对这个方法提供默认的一种实现。

  1. 使用 default 修饰接口中的 方法,必须有主体
  2. 接口的 default 方法不能够 被接口本身调用,需要接口的实现类(实现对象)来调用
  3. 接口的 default 方法可以被 子接口继承、重写、直接调用。
  4. 接口的 default 方法可以被 实现类重写 及 直接调用。(可以不需要重写即可直接使用)
public interface InterfaceText {
    default void testDefault(){
        System.out.println("我是接口中的静态方法");
    }
}
class  defaultTestClass implements InterfaceText{
   public void test1(){
       new defaultTestClass().testDefault();  // 调用接口中的 default 方法
   }
}

3. 函数式接口

3.1. 什么是 函数式接口

  1. 函数式接口(Functional Interface) 就是一个 有且仅有一个抽象方法
  2. 但是函数式接口 可以有多个 非抽象方法(static、default、private)。
  3. 可以使用 注解 @FunctionalInterface 标记该接口为函数式接口

3.2. 函数式接口注解

@FunctionalInterface

标记 函数式接口,可以用来检查 该接口是否符合函数式接口 格式。

3.3. 常用的函数式接口

3.3.1. Supplier 接口

Supplier: 包含一个无参的方法,有返回值。

T get(): 获得结果。

  • 该方法不需要参数,它会按照某种实现逻辑(Lambda表达式实现)返回一个数据。
  • Supplier接口也被称为生产型接口,如果我们指定了接口的泛型是什么类型,那么接口中的get方法就会生产什么类型的数据供我们使用。
public class getString {
    public static void main(String[] args) {
        /*String s = getString(() -> {
return "小曹";
});*/
        String s1 = getString(() -> "小王");
        System.out.println(s1);
        Integer integer = getInteger(() -> 20);
        System.out.println(integer);
    }
    //定义一个方法,返回一个整数数据
    private static Integer getInteger(Supplier<Integer> sup){
        return sup.get();
    }
    //定义一个方法,返回一个字符串数据
    private static String getString(Supplier<String> sup){
        return sup.get();
    }
}

3.3.2. Consumer接口

Consumer表示消耗,接口接受通用参数t,调用accept,对参数执行一系列操作,但没有返回值。

  • void accept(T t): 对给定的参数执行操作。
  • default Consumer andThen(Consumer after): 返回一个组合的Consumer,一次执行此操作,然后执行after操作。

Consumer接口也被称为消费型接口,它消费的数据的数据类型由泛型指定

public class ConsumerDemo {
    public static void main(String[] args) {
        /* operatorString("小曹",(String s)->{
System.out.println(s);
});*/
        operatorString("小曹",s-> System.out.println(s));
        operatorString("小曹",s-> System.out.println(new
                                                   StringBuilder(s).reverse().toString()));
        //方法引用
        //operatorString("小曹",System.out::printf);
        operatorString("林青霞",s-> System.out.println(s),s-> System.out.println(new
                                                                              StringBuilder(s).reverse().toString()));
    }
    //定义一个方法,用不同的方式消费一个字符串数据两次
    private static void operatorString(String name,Consumer<String>
                                       con1,Consumer<String> con2){
        /* con1.accept(name);
con2.accept(name);*/
        con1.andThen(con2).accept(name);
    }
    //定义一个方法,消费一个字符串数据
    private static void operatorString(String name, Consumer<String> con){
        con.accept(name);
    }
}

3.3.3. Predicate 接口

Predicate是Java中的一个函数式接口,它代表一个判断逻辑,接收一个输入参数,返回一个布尔值。

Predicate 常用的四个方法

  • boolean test(T t)对给定的参数进行判断(判断逻辑由Lambda表达式实现),返回一个布尔值。
  • default Predicate negate():返回一个逻辑的否定,对应逻辑非。
  • default Predicate and(Predicate other) :返回一个组合判断,对应短路与。
  • default Predicate or(Predicate other) :返回一个组合判断,对应短路或。
public class PredicateDemo1 {
    public static void main(String[] args) {
        /* boolean b = checkString("hello", (String s) -> {
return s.length() > 8;
});
*/      boolean b = checkString("helloword", s -> s.length() > 8);
        System.out.println(b);
    }
    //判断给定的字符串是否满足要求
    private static boolean checkString(String s, Predicate<String> pre){
        //return pre.test(s);
        //return !pre.test(s);
        //逻辑非
        return pre.negate().test(s);
    }
}

3.3.4. Function接口

接口是 Java 8 引入的一个函数式接口,它定义了一个具有单一输入参数和单一结果返回的函数。

Function<T,R> 接口通常用于对参数进行处理,转换(处理逻辑由lambda表达式实现)然后返回一个新的值。

该接口包含一个抽象方法 apply(T t),用于接受一个参数 T 并返回一个结果。

常用方法
  • R apply(T t) :用于接受一个参数 T 并返回一个结果。

T 函数输入的类型

R 函数的结果类型

  • default Function and Then(Function after): 返回一个组合函数,首先将该函数应用于输入,然后将after函数应用于结果
public class FunctionDemo {
    public static void main(String[] args) {
        /* convert("100",(String s)->{
return Integer.parseInt(s);
});*/
        convert("100",s->Integer.parseInt(s));
        //方法引用
        convert("100",Integer::new);
        convert(100,i->String.valueOf(i+566));
        convert("100",s->Integer.parseInt(s),i->String.valueOf(i+566));
    }
    //定义一个方法,把一个字符串转换为int类型,在控制台输出
    private static void convert(String s, Function<String,Integer> fun){
        int i = fun.apply(s);
        System.out.println(s);
    }
    //定义一个方法,把一个int类型的数据加上一个整数之后,转为字符串在控制台输出
    private static void convert(int i,Function<Integer,String> fun){
        String s = fun.apply(i);
        System.out.println(s);
    }
    //定义一个方法,把字符串转换int类型,把int类型的数据加上一个整数之后,转为字符串在控制台
    输出
    private static void convert(String s,Function<String,Integer>
                                fun1,Function<Integer,String> fun2){
        /* Integer i = fun1.apply(s);
String k = fun2.apply(i);
System.out.println(k);*/
        String s1 = fun1.andThen(fun2).apply(s);
        System.out.println(s1);
    }
}

4. Lambda 表达式(掌握)

4.1. 什么是 lambda 表达式

简单来说:可以看成 匿名内部类的简写,使用Lambda 表达式时,接口必须是函数式接口

4.2. Lambda 表达式的语法

<函数式接口>  <变量名> = (参数1,参数2...) -> {
        //方法体
   }

4.3. Lambda 的使用

@FunctionalInterface
public interface ISay {
    void say();
}
ISay iSay = new ISay() {
    @Override
    public void say() {
        System.out.println("人在说话...");
    }
}; 
iSay.say();x

lambda 表达式 的作用 就是为了简化:匿名内部类。 必须是函数式接口

ISay iSay1=()->{System.out.println("猫在喵喵喵");};
iSay1.say();

根据左边函数式接口 ,右边能够 自动推导 出写的哪一个方法。

4.4. lambda 表达式特点

参数1,参数2…)表示参数列表;->表示连接符;{}内部是方法体 。

  1. “=” 右边的类型 会根据 左边的函数式接口类型自动推断。
  2. 如果形参为空,只需要保留“()”。
  3. 如果形参只有 1 个,() 可以省略,只需要参数的名称即可。
  4. 如果执行语句只有1句,且无返回值,{}可以省略;若有返回值,则若想省去{},则必须同时省略return,且执行语句也保证只有1句
  5. 形参列表的数据类型 会自动推断。
  6. lambda 不会生成一个单独的 内部类文件。
  7. lambda 表达式若访问了局部变量,则局部变量必须是final的,

若局部变量没有加 final 关键字,系统会自动添加,此后再修改该局部变量,会报错。

案例1如下:有参函数式接口

public interface Ieat {d
    void eat(String food);
}d
public class Human {
    public static void main(String[] args) {
//------------------------匿名内部类---------------------
Ieat ieat = new Ieat() {
    @Override
    public void eat(String food) {
        System.out.println("人吃"+food);
    }
};
ieat.eat("螺蛳粉");
//----------------------lambda 表达式------------------
Ieat ieat1 = (String food)->{ System.out.println("狗吃"+food);};
ieat1.eat("屎");

// lambda 变形二: 只有一个参数的时候,() 、形参类型也可以省略;
//                只需要参数的名称即可
//                如果执行语句只有1句,且无返回值,{}可以省略
Ieat ieat2 = food -> System.out.println("猫"+food);
    }
}

案例二如下:有参有返回值 函数式接口

public interface Iexam {
     String exam(Integer num);
}
public class Human {
    public static void main(String[] args) {
//------------------------匿名内部类---------------------
        Iexam iexam = new Iexam() {
            @Override
            public String exam(Integer num) {
                return  num >60 ?"合格":"不合格";
            }
        };
        System.out.println(iexam.exam(60));
//----------------------lambda 表达式------------------
//若有返回值,则若想省去{},则必须同时省略return,且执行语句也保证只有1句
        Iexam iexam1 = num -> num>60?"合格啦":"不合格 请继续努力";
        System.out.println(iexam1.exam(70));
    }
}

4.5. Lambda 表达式 和 匿名内部类的区别?

  1. 所需类型不同
  • 匿名内部类:可以是接口,也可以是抽象类,还可以是具体类。
  • Lambda表达式:只能是接口。
  1. 使用限制不同
  • 如果接口中有且仅有一个抽象方法:可以使用Lambda 表达式,也可以使用匿名内部类。
  • 如果接口中有多于一个抽象方法,只能使用匿名内部类。
  1. 实现原理不同
  • 匿名内部类:编译之后产生一个单独的.class 字节码文件。
  • Lambda 表达式:编译之后,没有单独的. class 字节码文件。对应的字节码会在运行的时候动态生成。

5. lambda中方法引用【掌握】

5.1. 静态方法引用【掌握】

语法 :类名::静态方法名

注意事项:

  1. 被引用的 静态方法参数列表 和 函数式接口中抽象方法的参数一致
  2. 接口的 抽象方法有返回值,引用的静态方法必须有相同类型的返回值 !!
  3. 接口的 抽象方法没有返回值,引用的静态方法可以有返回值 也可以没有返回值

满足 抽象参数列表 与 引用参数列表相同,可以写成静态方法引用的格式 类名::静态方法名

案例1:

public interface Itransfer {
    Integer transfor(String str);
}
public class test01 {
    public static void main(String[] args) {
    //------------------------匿名内部类---------------------
        Itransfer itransfer = new Itransfer() {
            @Override
            public Integer transfor(String str) {
                return  Integer.valueOf(str);
            }
        };
        System.out.println(itransfer.transfor("10"));
    //------------------------lambda表达式---------------------
        Itransfer itransfer1 = str -> Integer.valueOf(str);
        System.out.println(itransfer1.transfor("50")+20);
    //------------------------方法引用---------------------
        Itransfer itransfer2= Integer::valueOf;
        itransfer.transfor("20");
    }
}

5.2. 实例方法引用【掌握】(***)

语法:类名:: 非静态方法名

注意事项:

  1. 引用的实例方法 参数列表 和 函数式接口中抽象方法 的参数一致
  2. 接口的抽象方法没有返回值,引用的实例方法可以有返回值也可以没有

3. 接口的抽象方法有返回值,引用的实例方法必须有相同类型的返回值!!

public class Person {
    public String say(String words){
        return "老王头总是说"+words;
    }
}
@FunctionalInterface
public interface ISpeek {
    String speekOne(String str);
}
public class test01 {
    public static void main(String[] args) {
 //------------------------匿名内部类---------------------
        ISpeek iSpeek = new ISpeek() {
            @Override
            public String speekOne(String str) {
                return new Person().say(str);
            }
        };
        System.out.println(iSpeek.speekOne("你好"));
//------------------------lambda表达式---------------------
        ISpeek iSpeek1= str -> new Person().say(str);
        System.out.println(iSpeek.speekOne("hhhh"));
  //------------------------方法引用---------------------
        ISpeek iSpeek2 = new Person()::say;
        System.out.println(iSpeek2.speekOne("方法引用调用的"));
        
    }

5.3. 构造方法引用【掌握】

语法:类名 :: new

注意事项:

  1. 构造方法 与 函数式接口的抽象方法 参数列表一致
public class Person {
    private String name;
    private Integer age;
    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
    public Person() {
    }
    @Override
    public String toString() {
        return "Person{" +
        "name='" + name + '\'' +
        ", age=" + age +
        '}';
    }
}
public interface IAnimal {
    Person create(String name,Integer age);
}
public class test01 {
    public static void main(String[] args) { 
        //------------------------匿名内部类---------------------
        IAnimal iAnimal = new IAnimal() {
            @Override
            public Person create(String name, Integer age) {
                return new Person(name,age);
            }
        };
        Person person = iAnimal.create("小可", 22);
        System.out.println(person);
        
        //------------------------lambda表达式---------------------
        IAnimal animal = (name,age)-> new Person(name,age);
        System.out.println(animal.create("小小",90));
        
        //------------------------方法引用---------------------
        IAnimal iAnimal1 = Person::new; //构造方法
        Person person1 = iAnimal.create("小曹", 21);
        System.out.println(person1);
    }
}

lambda 中调用的 变量 必须用final修饰。

6. Stream流

6.1. Stream 流的引入

在 Java8 之前,通常用 fori、for each 或者 Iterator 迭代来重排序合并数据,或者通过重新定义 Collections.sorts的 Comparator 方法来实现,这两种方式对 大数量系统来说,效率不理想。

Java8 中添加了一个新的接口类 Stream,相当于高级版的 Iterator,通过Lambda 表达式对集合进行各种非常便利、高效的聚合操作(Aggregate Operation),或者大批量数据操作 (Bulk Data Operation)。

Stream不仅可以通过串行的方式实现数据操作,还可以通过并行的方式处理大批量数据,提高数据的处理效率。

6.2. 什么是Stream流

Stream(流)是一个来自数据源的元素队列并支持聚合操作。

  1. 数据源 流的来源。 可以是集合、数组,I/O channel(nio new IO非阻塞式IO), 产生器generator 等。
  2. 聚合操作 类似SQL语句一样的操作,比如fiter、map、reduce、find、match、sorted等。
  3. Pipelining:中间操作都会返回对象本身。
  4. 内部迭代: 以前对集合遍历都是通过Iterator或者For-Each的方式,显式的在集合外部进行迭代, 这叫做外部迭代。 Stream提供了内部迭代的方式, 通过访问者模式(Visitor)实现。

6.2.1. Stream流的使用

  • 生成流

通过数据源(集合、数组等)生成流。list.stream()

  • 中间操作

一个流后面可以跟随零个或多个中间操作,其目的主要是打开流,做出某种程度的数据过滤/映射,然后返回一个新的流,交给下一个操作。filter()

  • 终结操作

一个流只能有一个终结操作,当这个操作执行后,流就被使用“光”了,无法再被操作。所以这必定是流的最后一个操作。forEach();

6.3. 生成流

在 Java 8 中, 集合接口有两个方法来生成流:

Stream() 是 Collection 类中的方法。

  • stream() : 为集合创建串行流。
  • parallelStream() : 为集合创建并行流
List<Integer> list = Arrays.asList(5, 2, 3, 1, 6, 10, 9);
list.stream();

6.4. Stream流的常见中间操作方法

6.4.1. filter 对流中数据过滤

Stream filter(Predicate predicate): 用于对流中的数据进行过滤

Predicate 接口中的方法 boolean test(T t):对给定的参数进行判断,返回一个布尔值

List<String> list = new ArrayList<>();
list.add("林青霞");
list.add("张曼玉");
list.add("王祖贤");
list.add("柳岩");
list.add("张敏");
list.add("张无忌");
//需求1 :把list集合中以张开头的元素在控制台输出
list.stream().filter(s -> s.startsWith("张")).forEach(System.out::println);
System.out.println("-----");
//需求2:把list集合中长度为3的元素在控制台输出
list.stream().filter(s -> s.length()==3).forEach(System.out::println);
System.out.println("------");
//需求3:把list集合中以张开头,长度为3的元素在控制台输出
list.stream().filter(s -> s.startsWith("张")).filter(s ->
                                                    s.length()==3).forEach(System.out::println);

6.4.2. map & mapTolnt -->从流中获取数据;。

Stream map(Function mapper) : 返回由该流的 元素 组成的流。

map 方法用于映射每个元素到对应的结果。

Function接口中的方法 R apply(T t)

List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5); 
// 获取对应的平方数 
numbers.stream().map( i -> i*i).forEach(System.out::println);

InStream mapTolnt(TolntFunction mapper) : 返回一个IntStream其中包含给定函数应用于此流的元素的结果。

IntStream: 表示元素int流

TolntFunction接口的方法 int applyAslnt(T value)

//创建一个集合,存储多个字符串元素
ArrayList<String> list = new ArrayList<>();
list.add("10");
list.add("20");
list.add("30");
list.add("40");
list.add("50");
//需求:将集合中的字符串数据转换为整数之后在控制台输出
list.stream().map(s -> Integer.parseInt(s)).forEach(System.out::println);
list.stream().map(Integer::parseInt).forEach(System.out::println);
//InStream mapTolnt(TolntFunction mapper) : 返回一个IntStream其中包含给定函
数应用于此流的元素的结果
//int applyAslnt(T value)
//InStream中的方法 int sum():返回此流中元素的总和
list.stream().mapToInt(Integer::parseInt).forEach(System.out::println);
int sum = list.stream().map

6.4.3. limit

Stream limit(long maxSize): 方法用于获取指定数量的流。

Random random = new Random();
//从随机流中获取十个随机数:并输出结果
random.ints().limit(10).forEach(System.out::println);

6.4.4. skip

Steam skip(long n):跳过指定参数个数的数据,返回由该流剩余元素组成的流

//创建一个集合,存储多个字符串元素
ArrayList<String> list = new ArrayList<>();
list.add("林青霞");
list.add("张曼玉");
list.add("王祖贤");
list.add("柳岩");
list.add("张敏");
list.add("张无忌");
//需求1: 取前三个数据在控制台输出
list.stream().limit(3).forEach(System.out::println);
System.out.println("--");
//需求2:跳过3个元素,把剩下的元素在控制台输出
list.stream().skip(3).forEach(System.out::println);
//需求3:跳过2个元素,把剩下的元素中前2个在控制台输出
list.stream().skip(2).limit(2).forEach(System.out::println);

6.4.5. concat

static Stream concat(Stream a,Stream b):合并a和b两个流为一个流。

6.4.6. distinct

Stream distinct() :返回由该流的不同元素(根据Object.equals(Object))组成流(去重复)

//创建一个集合,存储多个字符串元素
ArrayList<String> list = new ArrayList<>();
list.add("林青霞");
list.add("张曼玉");
list.add("王祖贤");
list.add("柳岩");
list.add("张敏");
list.add("张无忌");
//需求1:取前4个数据组成一个流
Stream<String> limit = list.stream().limit(4);
//需求2:跳过数据组成一个流
Stream<String> skip = list.stream().skip(2);
//需求3:合并需求1和需求2得到的流,并把结果在控制台输出
Stream.concat(limit,skip).forEach(System.out::println);

6.4.7. sorted

Stream sorted: 返回由此流的元素组成的流,根据自然顺序排序。

Stream sorted(Comparator comparator) : 返回由该流的元素组成的流,根据提供的Comparator进行排序。

//创建一个集合,存储多个字符串元素
ArrayList<String> list=new ArrayList<>();
list.add("lingqingxia");
list.add("zhangmanyu");
list.add("liuyan");
list.add("zhangmin");
list.add("zhangwuji");
//需求1:按照字母顺序把数据在控制台输出
list.stream().sorted().forEach(System.out::println);
//需求2:按照字符串长度把数据在控制台输出
//list.stream().sorted((s1,s2)->s1.length()-
s2.length()).forEach(System.out::println);
//长度相同按照自然顺序排序
list.stream().sorted((s1,s2)->{
    int num=s1.length()-s2.length();
    int num2=num==0?s1.compareTo(s2):num;
    return num2;
});

6.5. Stream 流的常见终结操作方法

  1. void forEach(Consumer action): 对此流的每个元素执行操作。

Consumer接口中的方法 void accept(T t):对给定的参数执行此操作

  1. long count():返回此流中的元素数
ArrayList<String> list = new ArrayList<>();
list.add("林青霞");
list.add("张曼玉");
list.add("王祖贤");
list.add("柳岩");
list.add("张敏");
list.add("张无忌");
//需求1:把集合中的元素在控制台输出
list.stream().forEach(s -> System.out.println(s));
list.stream().forEach(System.out::println);
//需求2: 统计集合中有几个以张开头的元素,并把统计结果在控制台输出
long count = list.stream().filter(s -> s.startsWith("张")).count();
System.out.println(count);

6.6. Stream流的收集操作

对数据使用Stream流的方式操作完毕后,我想把流中的数据收集到集合中,该怎么办呢?

6.6.1. Stream流的收集方法

R collect(Collector collector)

但是这个收集方法的参数是一个Collector接口

工具类Collectors提供了具体的收集方式

6.6.2. Collector toList()

public static Collector toList(): 把元素收集到List集合中

//创建list集合对象
List<String> list=new ArrayList<>();
list.add("林青霞");
list.add("张曼玉");
list.add("王祖贤");
list.add("张曼玉");
list.add("柳岩");
//需求1:得到名字为3个字的流
Stream<String> listStream = list.stream().filter(s -> s.length() == 3);
//需求2:把使用Stream流操作完毕的数据收集到list集合中并遍历
List<String> names = listStream.collect(Collectors.toList());
for (String name:names) {
    System.out.println(name);
}

6.6.3. Collector toSet()

public static Collector toSet(): 把元素收集到set集合中。

//创建set集合对象
Set<Integer> set = new HashSet<>();
set.add(10);
set.add(20);
set.add(30);
set.add(33);
//需求3:得到年龄大于25的流
Stream<Integer> setStream = set.stream().filter(s -> s > 25);
//需求4:把使用Stream流操作完毕的数据收集到set集合中并遍历
Set<Integer> ages = setStream.collect(Collectors.toSet());
for (Integer age:ages ) {
    System.out.println(age);
}

6.6.4. Collector toMap

public static Collector toMap(Function keyMapper,Function valueMapper) :把元素收集到map集合中

//定义一个字符串数组,每一个字符串数据由姓名数据和年龄数据组合而成
String[] strArray={"林青霞,30","张曼玉,35","王祖贤,33","柳岩,35"};
//需求5:得到字符串中年龄数据大于28的流
Stream<String> arrayStream = Stream.of(strArray).filter(s ->
                                                        Integer.parseInt(s.split(",")[1]) > 28);
//需求6:把使用Stream流操作完毕的数据收集到Map集合中并遍历,字符串中的姓名做
键,年龄做值
Map<String,Integer> map = arrayStream.collect(Collectors.toMap(s ->
                                                               s.split(",")[0], (String s) -> {
    return Integer.parseInt(s.split(",")[1]);
}
                                                              ));
for ( String key:map.keySet()) {
    Integer value=map.get(key);
    System.out.println(key+","+value);
}

7. Optional类

主要用于判空

  • Optional 类是一个可以为null的容器对象。
  • 如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。
  • Optional 是个容器:它可以保存类型T的值,或者仅仅保存null。
  • Optional 类的引入很好的解决空指针异常

7.1. Optional常用方法

  1. Optional.of(T t):创建要给Optional实例
  2. Optional.empty():创建一个空的Optional实例。
  3. Optional.ofNullable(T t):若t不为null,创建Optional实例,否则创建空的实例。
  4. isPresent():判断是否包含值。
  5. orElse(T t):如果调用对象包含值,返回该值,否则返回t。
  6. orElseGet(Supplier s):如果调用对象包含值,返回该值,否则返回s获取的值。
  7. map(function f):如果有值对其处理,并发挥处理后的Optional ,否则返回Optional.empty()。
  8. flatMap(Function mapper):与map类似,要求返回值必须

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值