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 协议》,转载必须注明作者和本文链接
推荐文章: