jdk 8 常用新特性代码样例
// 分组、统计数量
Map<String, Long> collect = list.parallelStream().collect(Collectors.groupingBy(ReportDetailInfo::getCourier,Collectors.counting()));
// 仅分组
Map<String, List<ReportDetailInfo>> collect = list.parallelStream().collect(Collectors.groupingBy(ReportDetailInfo::getCourier));
/**
java8新特性--Stream将List转为Map汇总
Stream将List转换为Map,使用Collectors.toMap方法进行转换
背景:User类,类中分别有id,name,age三个属性。List集合,userList,存储User对象
1、指定key-value,value是对象中的某个属性值。
Map<Integer,String> userMap1 = userList.stream().collect(Collectors.toMap(User::getId,User::getName));
2、指定key-value,value是对象本身,User->User 是一个返回本身的lambda表达式
Map<Integer,User> userMap2 = userList.stream().collect(Collectors.toMap(User::getId,User->User));
3、指定key-value,value是对象本身,Function.identity()是简洁写法,也是返回对象本身
Map<Integer,User> userMap3 = userList.stream().collect(Collectors.toMap(User::getId, Function.identity()));
4、指定key-value,value是对象本身,Function.identity()是简洁写法,也是返回对象本身,key 冲突的解决办法,这里选择第二个key覆盖第一个key。
Map<Integer,User> userMap4 = userList.stream().collect(Collectors.toMap(User::getId, Function.identity(),(key1,key2)->key2));
**/
// 判断NULL,抛异常
Optional.ofNullable(memberGoods).orElseThrow(()->{throw new AppException("");});
// 返回年纪最大对象
Optional<Employee > userOp= userList.stream().max(Comparator.comparingInt(Employee ::getAge));
Employee maxEmp = userOp.get();
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;
}
// Map用法
List<StaffPublic> result = staff.stream().map(temp -> {
StaffPublic obj = new StaffPublic();
obj.setName(temp.getName());
obj.setAge(temp.getAge());
if ("mkyong".equals(temp.getName())) {
obj.setExtra("this field is for mkyong only!");
}
return obj;
}).collect(Collectors.toList());
//flatMap - 将words数组中的元素再按照字符拆分,然后字符去重,最终达到["h", "e", "l", "o", "w", "r", "d"]
//如果使用map,是达不到直接转化成List<String>的结果
// 如果使用的是map方法,返回的是[ ...['y', 'o', 'u', 'r'], ['n', 'a', 'm', 'e']]
// 如果使用的是flatMap方法,返回的是['y', 'o', 'u', 'r', 'n', 'a', 'm', 'e']
List<String> stringList = words.stream()
.flatMap(word -> Arrays.stream(word.split(" ")))
.distinct() // 去重
.collect(Collectors.toList());
// 循环
stringList.forEach(e -> System.out.println(e));
// 分组,过滤
Map<String, List<Apple>> AppMap2=
appleList.stream()
.filter((Apple a)->a.getWeight()>150) //筛选出大于150的
.collect(groupingBy(Apple::getColor)); //按颜色分组 最后得到map
Map<Integer, List<User>> collect = list.stream().collect(Collectors.groupingBy(User::getAge));
// 计算&统计:
int max = numbers.stream().mapToInt(x -> x).max().getAsInt();
int min = numbers.stream().mapToInt(x -> x).min().getAsInt();
long count = numbers.stream().mapToInt(x -> x).count();
double avg = numbers.stream().mapToInt(x -> x).average().getAsDouble();
int sum = numbers.stream().mapToInt(x -> x).sum();
// 也可以用IntSummaryStatistics类来得到统计结果:
IntSummaryStatistics stat = numbers.stream().mapToInt(x -> x).summaryStatistics();
int max = stat.getMax();
int min = stat.getMin();
long count = stat.getCount();
double avg = stat.getAverage();
long sum = stat.getSum();
// 匿名类
import lombok.AllArgsConstructor;
import lombok.Data;
public @Data @AllArgsConstructor class Cat {
private String name;
private double height;
private double weight;
}
// public int compare(Cat o1, Cat o2)
Collections.sort(catList, (o1, o2) -> {
if (o1.getHeight() > o2.getHeight()) {
return 1;
} else if (o1.getHeight() < o2.getHeight()) {
return -1;
} else {
return 0;
}
});
// 排序
catList.sort(Comparator.comparing(Cat::getWeight));
// 逆向排列
catList.sort(Comparator.comparing(Cat::getWeight).reversed());
// 函数式接口
import java.util.function.Consumer;
import java.util.function.Predicate;
import lombok.AllArgsConstructor;
import lombok.Data;
// 有一个订单类,有id,金额,运费这些属性。这个订单有一个折扣方法,我们希望能够根据营销活动,动态修改优惠方案。
public @Data @AllArgsConstructor class Order {
private long id;
private double payment;
private double freight;
// 优惠政策
public Order discount(Order order, Predicate<Order> predicate, Consumer<Order> consumer) {
// 满足Predicate的条件,返回true
if (predicate.test(order)) {
// 接收订单对象,对订单对象进行处理
consumer.accept(order);
}
return order;
}
}
// 新建一个订单,506.5的金额,10.0的运费
Order order = new Order(123, 506.5, 10.0);
// 满足金额>=99的条件,则设置运费为0
order.discount(order, o -> o.getPayment() >= 99, o -> o.setFreight(0));
// reduce() :把Stream 元素组合起来(从1加到5),例如,字符串拼接,数值的 sum,min,max ,average 都是特殊的 reduce。
public static void test5() {
List list = new ArrayList();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
System.out.println(list.stream().reduce((param1, param2) -> (int) param1 + (int) param2).get());
}
// min(),max() 找到最大值最小值
list.stream().min((param1, param2) -> (int) param1 > (int) param2 ? 1 : -1).get();
list.stream().max((param1, param2) -> (int) param1 > (int) param2 ? 1 : -1).get();
/**
总结:
1. 流式操作的引入:提高执行效率(并行),方便编码(有很多API 可用),提高可读性。
2. 流的分类:可以分为串行流和并行流;对于操作:可以分为中间操作和最终操作
3. 流API:
中间操作:
filter(): 对元素进行过滤;
sorted():对元素排序;
map():元素映射;
distinct():去除重复的元素 。
最终操作:
forEach():遍历每个元素;
reduce():把Stream 元素组合起来。例如,字符串拼接,数值的 sum,min,max ,average 都是特殊的 reduce。
collect():返回一个新的集合。
min():找到最小值。
max():找到最大值。
Ps1:除了上面介绍的方法,还有如下方法:
Intermediate:
map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered
Terminal:
forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator
Short-circuiting:
anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 limit
**/
/**
* 多条件去重
* @param list
*/
public static void order() {
list.stream().collect(Collectors.collectingAndThen(
Collectors.toCollection(() -> new TreeSet<>(
Comparator.comparing(o -> o.getAge() + ";" + o.getName()))), ArrayList::new)).forEach(u -> println(u));
}
/**
* 转set
*/
public static void toSet() {
Set<User> collect = list.stream().collect(Collectors.toSet());
Iterator<User> iterator = collect.iterator();
while(iterator.hasNext()) {
System.out.println(iterator.next().getUserId());
}
}
/**
* 转map
*/
public static void toMap() {
Map<Integer, User> collect = list.stream().collect(Collectors.toMap(User::getUserId, u -> u));
for (Integer in : collect.keySet()) {
User u = collect.get(in);//得到每个key多对用value的值
println(u);
}
}
/**
*map
*/
public static void map() {
list.stream().map(User::getUserId).forEach(userId -> println(userId));
list.stream().mapToInt(User::getAge).forEach(userId -> println(userId));
list.stream().mapToDouble(User::getUserId).forEach(userId -> println(userId));
list.stream().mapToLong(User::getUserId).forEach(userId -> println(userId));
}
/**
* 查找与匹配
* allMatch方法与anyMatch差不多,表示所有的元素都满足才返回true。noneMatch方法表示没有元素满足
*/
public static void anyMatch() {
boolean anyMatch = list.stream().anyMatch(u -> u.getAge() == 100);
boolean allMatch = list.stream().allMatch(u -> u.getUserId() == 10);
boolean noneMatch = list.stream().noneMatch(u -> u.getUserId() == 10);
println(anyMatch);
println(allMatch);
println(noneMatch);
}
/**
* reduce操作
*/
public static void reduce() {
Optional<Integer> sum = list.stream().map(User::getAge).reduce(Integer::sum);
Optional<Integer> max = list.stream().map(User::getAge).reduce(Integer::max);
Optional<Integer> min = list.stream().map(User::getAge).reduce(Integer::min);
println(sum);
println(max);
println(min);
}
/**串行排序**/
List<String> list = new ArrayList<String>();
for(int i=0;i<1000000;i++){
double d = Math.random()*1000;
list.add(d+"");
}
long start = System.nanoTime();//获取系统开始排序的时间点
int count= (int) ((Stream) list.stream().sequential()).sorted().count();
long end = System.nanoTime();//获取系统结束排序的时间点
long ms = TimeUnit.NANOSECONDS.toMillis(end-start);//得到串行排序所用的时间
System.out.println(ms+”ms”);
/**并行排序:**/
List<String> list = new ArrayList<String>();
for(int i=0;i<1000000;i++){
double d = Math.random()*1000;
list.add(d+"");
}
long start = System.nanoTime();//获取系统开始排序的时间点
int count = (int)((Stream) list.stream().parallel()).sorted().count();
long end = System.nanoTime();//获取系统结束排序的时间点
long ms = TimeUnit.NANOSECONDS.toMillis(end-start);//得到并行排序所用的时间
System.out.println(ms+"ms");
// 串行输出为 1200ms,并行输出为 800ms。可见,并行排序的时间相比较串行排序时间要少不少。