淘先锋技术网

首页 1 2 3 4 5 6 7

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。可见,并行排序的时间相比较串行排序时间要少不少。