概述
java8一大特点就是lambda表达式,简化代码,稍微总结一下一些常用的语法。
Optional
优雅的判空,代替繁琐的 xxx!=null
写法简化代码
Optional常用方法:
1、Optional(T value),empty(),of(T value),ofNullable(T value)
- Optional(T value),即构造函数,它是private权限的,不能由外部调用的。其余三个函数是public权限,供程序员所调用。Optional的本质,就是内部储存了一个真实的值,在构造的时候,就直接判断其值是否为空。
- of(T value)函数内部调用了构造函数,源码如下:
public static <T> Optional<T> of(T value) {
return new Optional<>(value);
}
- empty()的作用就是返回EMPTY对象。源码如下:
public final class Optional<T> {
// 省略....
private static final Optional<?> EMPTY = new Optional<>();
private Optional() {
this.value = null;
}
// 省略...
public static<T> Optional<T> empty() {
@SuppressWarnings("unchecked")
Optional<T> t = (Optional<T>) EMPTY;
return t;
}
}
- ofNullable(T value),相比较of(T value)的区别就是,当value值为null时,of(T value)会报NullPointerException异常;ofNullable(T value)不会throw Exception,ofNullable(T value)直接返回一个EMPTY对象。(这个比较常用)源码如下:
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
2、orElse(T other),orElseGet(Supplier<? extends T> other) 和 orElseThrow(Supplier<? extends X> exceptionSupplier)
三个函数都是在构造函数传入的value值为null时,进行调用的。
- orElse 和 orElseGet的用法如下所示,相当于value值为null时,给予一个默认值。用法如下:
@Test
public void test() {
User user = null;
user = Optional.ofNullable(user).orElse(createUser());
user = Optional.ofNullable(user).orElseGet(() -> createUser());
}
public User createUser(){
User user = new User();
user.setName("zhangsan");
return user;
}
这两个函数的区别:当user值不为null时,orElse函数依然会执行createUser()方法,而orElseGet函数并不会执行createUser()方法。
- orElseThrow,就是value值为null时,直接抛一个异常出去,用法如下:
User user = null;
Optional.ofNullable(user).orElseThrow(()->new Exception("用户不存在"));
3、map(Function<? super T, ? extends U> mapper) 和 flatMap(Function<? super T, Optional> mapper)
这两个函数都是做一些值转换的操作的,源码如下:
public final class Optional<T> {
// 省略....
public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Optional.ofNullable(mapper.apply(value));
}
}
// 省略...
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Objects.requireNonNull(mapper.apply(value));
}
}
}
这两个函数,在函数体上没什么区别。唯一区别的就是入参,map函数所接受的入参类型为Function<? super T, ? extends U>,而flapMap的入参类型为Function<? super T, Optional<U.>>。用法如下:
public void getCity8(User user) throws Exception {
// User::getAddress <=> u->u.getAddress()
String city = Optional.ofNullable(user)
.map(User::getAddress)
.map(Address::getCity)
.orElseThrow(() -> new Exception("map() 取值错误"));
String city2 = Optional.ofNullable(user)
.flatMap(u -> Optional.ofNullable(u.getAddress()))
.flatMap(ad -> Optional.ofNullable(ad.getCity()))
.orElseThrow(() -> new Exception("flatMap() 取值错误"));
System.out.println("city: " + city + ", " + city2);
}
4、isPresent() 和 ifPresent(Consumer<? super T> consumer)
顾名思义,isPresent 是判断 value 值是否为空,而 ifPresent 就是在value值不为空时,做一些操作。源码如下:
public final class Optional<T> {
//省略....
public boolean isPresent() {
return value != null;
}
//省略...
public void ifPresent(Consumer<? super T> consumer) {
if (value != null)
consumer.accept(value);
}
}
5、filter(Predicate<? super T> predicate)
filter() 是用来过滤筛选数据的,跟过滤器一个理儿。源码如下:
public final class Optional<T> {
//省略....
Objects.requireNonNull(predicate);
if (!isPresent())
return this;
else
return predicate.test(value) ? this : empty();
}
filter 方法接受一个 Predicate 来对 Optional 中包含的值进行过滤,如果包含的值满足条件,那么还是返回这个 Optional;否则返回 Optional.empty。用法如下:
Optional<User> user1 = Optional.ofNullable(user).filter(u -> u.getName().length()<6);
以上摘自 https://blog.csdn.net/zjhred/article/details/84976734
Stream
流式编程,常用语集合上,常用方法跟 Optional 的有些方法一样。这里列举一下常用例子。
常用方法使用案例
List<User> users = new ArrayList<User>()
例1: filter() & collect(Collectors.toList()) 过滤数据得到一个新的集合。
List<User> usersList = users.stream()
.filter(u -> u.getAge() > 3)
.collect(Collectors.toList());
例2: collect(Collectors.toMap()) 把 list 集合转成 map,这里也可结合 filter() 使用
这里不会覆盖相同key,而是拼接。如果要覆盖,只留一个key即可:(key1, key2) -> key2
Map<Integer, String> stringMap = users.stream()
.collect(
Collectors.toMap(
User::getAge,
User::getName,
(key1, key2) -> key1 + "," + key2
));
List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5);
例3: map() 将 List<Integer>
转成 List<String>
List<String> result1 = integerList.stream()
.map(value -> String.format("String:%s", value)).collect(toList());
System.out.println("result1: " + JSON.toJSONString(result1));
输出结果:
result1: ["String:1","String:2","String:3","String:4","String:5"]
例4: flatMap() 将每个 Integer 元素都生成一个新的 Stream 并将这些 Stream 连接成一个新的 Stream
List<Integer> result2 = integerList.stream().flatMap(value -> {
Integer[] is = new Integer[value];
for (int i = 0; i < value; i++) {
is[i] = value;
}
return Stream.of(is);
}).collect(toList());
System.out.println("result2: " + JSON.toJSONString(result2));
输出结果:
result2:[1,2,2,3,3,3,4,4,4,4,5,5,5,5,5]
例5: reduce() 求List中所有元素之和
reduce 函数的一个参数为循环的初始值,这里计算累加时初始值为 0,acc 代表已经计算的结果,item 表示循环的每个元素。
Integer sum = integerList.stream().reduce(0, (acc, value) -> acc + value);
System.out.println("sum: " + sum);
输出结果:
sum: 15
例6: 取List中的最大值 和 最小值
min 和 max 函数需要一个 Comparator 对象为参数作为比对依据
Comparator<Integer> comparator = Integer::compareTo;
System.out.println("min: " + integerList.stream().min(comparator).get());
System.out.println("max: " + integerList.stream().max(comparator).get());
输出结果:
min: 1
max: 5
例7 groupingBy 对list进行分组,类似数据库sql的 group by xxx
Product
实体类:
public class Product {
private Long id;
private Integer num;
private BigDecimal price;
private String name;
private String category;
}
List<Product> prodList = new ArrayList<Product>()
1、按照类目分组
Map<String, List<Product>> prodMap01 = prodList.stream()
.collect(Collectors.groupingBy(Product::getCategory));
// 统计总数
Map<String, Long> prodMap05 = prodList.stream()
.collect(Collectors.groupingBy(Product::getCategory, Collectors.counting()));
// 求和
Map<String, Integer> prodMap06 = prodList.stream()
.collect(Collectors.groupingBy(
Product::getCategory,
Collectors.summingInt(Product::getNum)));
例8 compute() 统计一句英语中每个字母出现的次数
String str = "hello java, nice to meet you.";
HashMap<Character, Integer> result2 = new HashMap<>(32);
for (int i = 0; i < str.length(); i++) {
char curChar = str.charAt(i);
result2.compute(curChar, (k, v) -> v == null ? 1 : v + 1);
}
System.out.println(result2);
输出结果:
{ =6, a=2, c=1, e=4, h=1, i=1, j=1, ,=1, l=2, m=1, .=1, n=1, o=3, t=2, u=1, v=1, y=1}
——————————————————————— End ——————————————————————————————
有不足之处 或者 语法用法有误 的地方还请指正