stream().filter集合过滤
public class Test {
public static void main(String[] args){
List<Person> array = new ArrayList<>();
array.add(new Person("AA",26,"男"));
array.add(new Person("BB",26,"女"));
array.add(new Person("DD",36,"男"));
array.add( new Person("EE",46,"女"));
array.add(new Person("FF",56,"男"));
array.add(new Person("GG",56,"男"));
/**
* 按年龄降序/升序
*/
//通过匿名内部类的方式重写Comparator比较器接口的compare方法
Collections.sort(array, new Comparator<Person>() {
// 升序排的话就是第一个参数.compareTo(第二个参数);
// 降序排的话就是第二个参数.compareTo(第一个参数);
@Override
public int compare(Person o1, Person o2) {
//升序
return o1.getAge().compareTo(o2.getAge());
}
});
System.out.println(array);
//用Lambda表达式简化,只写我们关注的:传入的参数,返回的值
Collections.sort(array,(p1,p2) -> p2.getAge().compareTo(p1.getAge()));//降序
System.out.println(array);
//更简洁地表明是通过那个属性的比较来进行排序,为什么说更简洁?因为comparing方法已经帮我们又封装了一层:
//下面源码可见:(c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
array.sort(Comparator.comparing(Person::getAge).reversed());//降序
array.forEach(System.out::println);
/**
* comparing的源码:
*
* public static <T, U extends Comparable<? super U>> Comparator<T> comparing(
* Function<? super T, ? extends U> keyExtractor)
* {
* Objects.requireNonNull(keyExtractor);
* return (Comparator<T> & Serializable)
* (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
* }
*/
//==========上面主要展示的就是关于集合根据属性值比较的排序===========
//==============接着讲一下stream的API:filter============
/**
* 输出age大于36的Person对象
*/
List<Person> collect = array.stream() //获取stream对象
.filter(s -> s.getAge() > 36) //中间操作:filter -> 可理解为过滤
.collect(Collectors.toList()); //终端输出:构建数据的输出
System.out.println(collect);
/**
* 获取空字符串的数量。
*
* 不知天高地厚多说两句(可能有点飘):
* 其实像用stream操作字符串、数组我相信大家都是很快上手的。
* 因为无非就是filter(设置过滤的条件)、map(映射每个元素到对应的结果)、list(获取指定数量的流),
* 但其实实际项目中操作字符串和数组是很少很少的,通常都是操作集合,如:集合之间的遍历比对,集合之间的转换、
* 集合的排序(上面已介绍,如应用于项目中:商品列表的排序,同一个子目录的商品,但我就想某一个放在前面,因为那个
* 商家给的广告费多,因此就可以为所有的商品都包含一个排序的属性,通过降序,设定属性值大的商品就会自动排在列表的前面。
*/
List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
long count = strings.stream().filter(string -> string.isEmpty()).count();
//==============继续流程,stream的API-map:map 方法用于映射每个元素到对应的结果============
/**
* 获取对应的平方数并去重,distinct()可理解为去重,也很有意思,下面会展示
*/
List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
List<Integer> squaresList = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList());
//==============再继续流程,stream的API-limit:limit 方法用于获取指定数量的流============
Random random = new Random();
//生成10个[10,100)范围内的数据
random.ints(1,10).limit(10).forEach(System.out::println);
//==============流程未完,重点:stream的API-distinct:distinct 方法用于获取指定数量的流============
/**
* 对Person的属性age去重后输出所有的age
*/
List<Integer> collect1 = array.stream()
.map(Person::getAge)
.distinct()
.collect(Collectors.toList());
collect1.sort(Comparator.naturalOrder());//升序,这里不是上面的对象排序,只是简单的元素排序
// collect1.sort(Comparator.reverseOrder());//降序
collect1.forEach(System.out::println);
//其实distinct不一定是唯一的方法,由于Set集合的机制,一样可以办到。
Set<Integer> collectSet = array.stream()
.map(Person::getAge)
.collect(Collectors.toSet());
collect1.forEach(System.out::println);
/**
* 根据属性去重,打印去重后的属性似乎不是什么难事,但实际上Person对象本身并没有任何的改变
*
* 那如果根据属性去重,而去除对象呢?我在在实际项目中还没有遇到如此奇葩的场景,但学习一下其用法也无妨
* 推荐博客:https://blog.csdn.net/haiyoung/article/details/80934467
* 下面快速介绍用法:
* 1、在Test类中实现distinctByKey方法,代码在最后。注意:不要写在main方法里
* 2、然后就可以通过filter调用 distinctByKey去重,b -> b.getAge()可理解为去重b这个对象,依据是b的属性age。
*/
List<Person> collect2 = array.stream()
.filter(distinctByKey(b -> b.getAge()))
.collect(Collectors.toList());
collect2.forEach(b -> System.out.println(b.getName()+ "," + b.getAge()));
//==============流程收尾,stream的API-reduce:reduce 方法用于累加
Integer reduce = array.stream()
.map(Person::getAge)
.reduce(0, Integer::sum);
System.out.println("sum = "+reduce);
//==============流程完结,业务逻辑的巧点:List转化为Map============
Map<String, String> map = array.stream()
.collect(Collectors.toMap(Person::getName, Person::toString));
map.entrySet().forEach(System.out::println);
map.forEach((k,v)->System.out.println("name : " + k + " toString : " + v));
}
}
/**
* 配合对象去重的实现方法
*/
private static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
Map<Object,Boolean> seen = new ConcurrentHashMap<>();
return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
}
}