Java8 常用方法

Map

compute

V compute(K key, BiFunction < ? super K, ? super V, ? extends V> remappingFunction)

指定的key在map中的值进行操作,不管存不存在,操作完成后保存到map中

public static void main(String[] args) {
    Map<String, Integer> map = new HashMap<>();
    map.put("1",1);
    map.put("2",2);
    map.compute("1", (k,v)-> {
        System.out.println("key = " + k + ", value = " + v);
        if (v != null) {
            return v+1;
        } else {
            return 0;
        }
    });
    map.compute("3", (k,v)->{
        System.out.println("key = " + k + ", value = " + v);
        if (v != null) {
            return v+1;
        } else {
            return 0;
        }
    });
    System.out.println(map.toString());
}

控制台打印

key = 1, value = 1
key = 3, value = null
{1=2, 2=2, 3=0}

computeIfAbsent

V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction)

computeIfAbsent的方法有两个参数 第一个是所选map的key,第二个是需要做的操作。这个方法当key值不存在时才起作用。

当key存在返回当前value值,不存在执行函数并保存到map中。

public static void main(String[] args) {
    Map<String, Integer> map = new HashMap<>();
    map.put("1",1);
    map.put("2",2);
    // key存在返回value
    Integer integer1 = map.computeIfAbsent("2", key -> new Integer(10));
    // key不存在执行函数存入
    Integer integer2 = map.computeIfAbsent("3", key -> new Integer(20));
    System.out.println("integer1 = " + integer1);
    System.out.println("integer2 = " + integer2);
    System.out.println(map.toString());
}

控制台打印

integer1 = 2
integer2 = 20
{1=1, 2=2, 3=20}

computeIfPresent

V computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction)

对指定的 在map中已经存在的key的value进行操作。只对已经存在key的进行操作,其他不操作

public static void main(String[] args) {
    HashMap<String,Integer> map = new HashMap<>();
    map.put("1",1);
    map.put("2",2);
    map.put("3",3);
    // 只对 map 中存在的key对应的value进行操作
    Integer integer1 = map.computeIfPresent("3", (k,v) -> {
        System.out.println("key = " + k + ", value = " + v);
        return v+1;
    });
    Integer integer2 = map.computeIfPresent("4", (k,v) -> {
        System.out.println("key = " + k + ", value = " + v);
        return v+1;
    } );
    System.out.println("integer1 = " + integer1);
    System.out.println("integer2 = " + integer2);
    System.out.println(map.toString());
}

控制台打印

key = 3, value = 3
integer1 = 4
integer2 = null
{1=1, 2=2, 3=4}

Optional

of(T value)

Student student = new Student();
// 如果 student 为 null,则会抛出NullPointerException
// 适用于 student 不为空的情况
Optional<Student> opt = Optional.of(student);

ofNullable(T value)

Student student = new Student();
// student 为 null 时不会报错
Optional<User> opt = Optional.ofNullable(user);
// 若 student 不为空,则返回true,否则返回false
System.out.println(opt.isPresent());

获取对象值

Student student = new Student();
// student 为 null 时不会报错
Optional<User> opt = Optional.ofNullable(user);
// 若 student 不为空,则返回true,否则返回false
System.out.println(opt.isPresent());
// 若 student 为 null, opt.get() 会报错
// 若 student 不为null,则返回对象值
System.out.println(opt.get());

检查是否有值的另一个选择是 ifPresent() 方法。该方法除了执行检查,还接受一个Consumer(消费者) 参数,如果对象不是空的,就对执行传入的 Lambda 表达式。

Student student = new Student();
Optional<Student> opt = Optional.ofNullable(student);
// 只有当 student 不为空时才会执行 ifPresent 方法里面的表达式
opt.ifPresent(u -> {
    System.out.println("username = " + u.getUsername());
});

返回默认值

orElse(T other)

Student student1 = null;
Student student2 = new Student();
student2.setUsername("lizhencheng");
Student optStudent = Optional.ofNullable(student1).orElse(student2);
System.out.println(optStudent.getUsername());

这里 student1对象是空的,所以返回了作为默认值的 student2。

如果对象的初始值不是 null,那么默认值会被忽略:

Student student1 = new Student();
student1.setUsername("lzc");
Student student2 = new Student();
student2.setUsername("lizhencheng");
Student optStudent = Optional.ofNullable(student1).orElse(student2);
System.out.println(optStudent.getUsername());

orElseGet(Supplier<? extends T> other)

这个方法会在有值的时候返回值,如果没有值,它会执行作为参数传入的 Supplier(供应者) 函数式接口,并将返回其执行结果:

Student student1 = new Student();
student1.setUsername("lzc");
Student optStudent = Optional.ofNullable(student1).orElseGet(()->{
    Student student2 = new Student();
    student2.setUsername("lizhencheng");
    return student2;
});
// 如果 student1 为 null,控制台则打印 "lzc" ,否则打印 "lizhencheng"
System.out.println(optStudent.getUsername());

orElse() 和 orElseGet() 的不同之处

public class Main {
    public static void main(String[] args) {
        Student student1 = new Student();
        student1.setUsername("lzc");

        System.out.println("orElse......");
        Student optStudent1 = Optional.ofNullable(student1).orElse(createNewStudent());
        System.out.println("orElseGet......");
        Student optStudent2 = Optional.ofNullable(student1).orElseGet(()-> createNewStudent());

        System.out.println(optStudent1.getUsername());
        System.out.println(optStudent2.getUsername());
    }

    public static Student createNewStudent() {
        System.out.println("createNewStudent......");
        Student student = new Student();
        student.setUsername("lizhencheng");
        return student;
    }
}

控制台打印结果

orElse......
createNewStudent......
orElseGet......
lzc
lzc

这个示例中,两个 Optional 对象都包含非空值,两个方法都会返回对应的非空值。不过,orElse() 方法仍然创建了 User 对象。与之相反,orElseGet() 方法不创建 User 对象。在执行较密集的调用时,比如调用 Web 服务或数据查询,这个差异会对性能产生重大影响。

返回异常

Student student = null;
Student optStudent = Optional.ofNullable(student).orElseThrow(() -> new IllegalArgumentException("参数不能为空"));

如果 student值为 null,会抛出 IllegalArgumentException。

这个方法让我们有更丰富的语义,可以决定抛出什么样的异常,而不总是抛出 NullPointerException。

转换值

Student student = new Student("lzc","1班");
String str = Optional
                .ofNullable(student)
                .map(s -> s.getUsername())
                .orElse("lizhencheng");
System.out.println(str);

过滤值

Student student = new Student("lzc","1班");
Optional<Student> temp = Optional
    .ofNullable(student)
    .filter(s -> s.getUsername() != null && s.getUsername().length() >= 3);
System.out.println(temp.isPresent());

Stream

forEach

default void forEach(Consumer<? super T> action)

遍历列表元素

List<String> list = new ArrayList<>();
list.add("123");
list.add("456");
list.forEach(s -> System.out.println(s));

filter

Stream<T> filter(Predicate<? super T> predicate)
List<String> list = new ArrayList<>();
list.add("123");
list.add("456789");
List<String> resultList = list
    .stream()
    .filter(s -> s.length() > 3)
    .collect(Collectors.toList());
resultList.forEach(s -> System.out.println(s));

Collectors.toList()可以把流转换为 List 类型或者是Set类型

distinct

Stream<T> distinct()

去除重复元素,这个方法是通过类的 equals 方法来判断两个元素是否相等的

List<String> list = new ArrayList<>();
list.add("123");
list.add("123");
list.add("456789");
List<String> resultList = list
    .stream()
    .distinct()
    .collect(Collectors.toList());
resultList.forEach(s -> System.out.println(s));

sorted

Stream<T> sorted()

Stream<T> sorted(Comparator<? super T> comparator)

如果流中的元素的类实现了 Comparable 接口,即有自己的排序规则,那么可以直接调用 sorted() 方法对元素进行排序。

方法一

List<Student> list = new ArrayList<>();
list.add(new Student("zhangsan",16));
list.add(new Student("lisi",20));
list.add(new Student("wangwu",18));

List<Student>  resultList = list
    .stream()
    .sorted((s1,s2) -> s1.getAge() - s2.getAge())
    .collect(Collectors.toList());

resultList.forEach(s -> System.out.println(s.toString()));

方法二

List<Student> list = new ArrayList<>();
list.add(new Student("zhangsan",16));
list.add(new Student("lisi",20));
list.add(new Student("wangwu",18));

List<Student>  resultList = list
                .stream()
                //.sorted(Comparator.comparing(Student::getAge)) // 升序
                .sorted(Comparator.comparing(Student::getAge).reversed()) // 降序
                .collect(Collectors.toList());

resultList.forEach(s -> System.out.println(s.toString()));

limit

Stream<T> limit(long maxSize)

返回前 n 个元素

List<Student> list = new ArrayList<>();
list.add(new Student("zhangsan",16));
list.add(new Student("lisi",20));
list.add(new Student("wangwu",18));

List<Student>  resultList = list
                .stream()
                .limit(2)
                .collect(Collectors.toList());

resultList.forEach(s -> System.out.println(s.toString()));

skip

Stream<T> skip(long n)

去除前 n 个元素

List<Student> list = new ArrayList<>();
list.add(new Student("zhangsan",16));
list.add(new Student("lisi",20));
list.add(new Student("wangwu",18));

List<Student>  resultList = list
                .stream()
                .skip(2)
                .collect(Collectors.toList());

resultList.forEach(s -> System.out.println(s.toString()));

map

<R> Stream<R> map(Function<? super T, ? extends R> mapper)

将流中的每一个元素 T 映射为 R(类似类型转换)

List<Student> list = new ArrayList<>();
list.add(new Student("zhangsan",16));
list.add(new Student("lisi",20));
list.add(new Student("wangwu",18));

List<String>  resultList = list
                .stream()
                .map(s -> {
                    String username = s.getUsername();
                    return username;
                }).collect(Collectors.toList());

resultList.forEach(s -> System.out.println(s.toString()));

flatMap

<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper)

将流中的每一个元素 T 映射为一个流,再把每一个流连接成为一个流

List<String> list = new ArrayList<>();
list.add("aaa bbb ccc");
list.add("ddd eee fff");
list.add("ggg hhh iii");

List<String> resultList = list
                .stream()
                .map(s -> s.split(" "))
                .flatMap(Arrays::stream).collect(Collectors.toList());

resultList.stream().forEach(s -> System.out.println(s));

上面例子中,我们的目的是把 List 中每个字符串元素以” “分割开,变成一个新的 List。
首先 map 方法分割每个字符串元素,但此时流的类型为 Stream<String[ ]>,因为 split 方法返回的是 String[ ] 类型;所以我们需要使用 flatMap 方法,先使用Arrays::stream将每个 String[ ] 元素变成一个 Stream 流,然后 flatMap 会将每一个流连接成为一个流,最终返回我们需要的 Stream。

anyMatch

boolean anyMatch(Predicate<? super T> predicate)

流中是否有一个元素匹配给定的 T -> boolean 条件

List<Student> list = new ArrayList<>();
list.add(new Student("zhangsan",16));
list.add(new Student("lisi",20));
list.add(new Student("wangwu",18));
// 是否存在一个 Student 对象的 age >= 20
boolean b = list.stream().anyMatch(s -> s.getAge() >= 20);
System.out.println(b);

allMatch

boolean allMatch(Predicate<? super T> predicate)

流中是否所有元素都匹配给定的 T -> boolean 条件

collect

<R, A> R collect(Collector<? super T, A, R> collector)

joining

joining 连接字符串

对流里面的字符串元素进行连接

List<String> list = new ArrayList<>();
list.add("123");
list.add("456");
list.add("789");
String collect = list.stream().collect(Collectors.joining(","));
System.out.println(collect);

toList/toSet

toList或者toSet,将数据流转换成List类型或者是Set类型

List<String> list = new ArrayList<>();
list.add("123");
list.add("456789");
List<String> resultList = list
    .stream()
    .filter(s -> s.length() > 3)
    .collect(Collectors.toList());
resultList.forEach(s -> System.out.println(s));

groupingBy

groupingBy 用于将数据分组,最终返回一个 Map 类型

List<Student> list = new ArrayList<>();
list.add(new Student("zhangsan",16));
list.add(new Student("lisi",2));
list.add(new Student("lzc",18));
list.add(new Student("xiaohong",1));
list.add(new Student("xiaoming",18));
list.add(new Student("lili",2));

Map<Integer, List<Student>> collect =
    list.stream()
    // .collect(Collectors.groupingBy(Student::getAge)); // 这样是无序的
    // .collect(Collectors.groupingBy(Student::getAge, TreeMap::new,Collectors.toList())); // 升序
    .collect(Collectors.groupingBy(Student::getAge, (() -> new TreeMap().descendingMap()),Collectors.toList())); // 降序

for (Integer key : collect.keySet()) {
    List<Student> students = collect.get(key);
    System.out.println("age = " + key);
    students.forEach(s -> System.out.println(s.toString()));
}

groupingBy 可以接受一个第二参数实现多级分组:

Map<Integer, Map<String, List<Student>>> collect =
    list.stream()
    .collect(
        Collectors.groupingBy(
            Student::getAge, 
            Collectors.groupingBy(Student::getUsername)
        )
);

收集数据

list.stream().collect(Collectors.groupingBy(Student::getAge, Collectors.summingInt(Student::getAge)));

partitioningBy

Map<Boolean, List<Student>> collect = list.stream().collect(Collectors.partitioningBy(s -> s.getAge() > 1));

partitioningBy 也可以添加一个收集器作为第二参数,进行类似 groupBy 的多重分区等等操作。

本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!