集合进阶
不可变集合
·如果某个数据不能被改变,把它放到不可变集合中是个很好的实践。
·当对象集合被不可信的库调用时,不可变形式是安全的。
简单理解:不想让别人修改集合中的内容。
在List、Set、Map接口中,都存在静态的of方法,可以获取一个不可变的集合。
static <E> List<E> of(E...elements);//创建一个有指定元素的List集合
static <E> Set> of(E...elements);//创建一个有指定元素的Set集合
static <E> Map> of(E...elements);//创建一个有指定元素的Map集合
//Map中的of方法最多传递20个数据,10个键值对,如果元素个数超过20个,先创建Map集合,元素放进去以后再调用Copyof方法即可。
Stream流
优点:结合Lambda表达式,简化集合、数组的操作。
使用步骤:
1、先得到一个Stream流(流水线),并把数据放上去。
单列集合:default<E>stream(); //Collection中的默认方法
双列集合:无 //无法直接使用stream流,需要用entry Set()转为单列集合。
数组:public static <T> Stream <T>stream(T[] arr);//Arrays工具类中的静态方法。
一堆零散数据:public static <T> Stream <T>of(T....value);//Stream接口中的静态方法。注意:也可以放入数组,但是只能方引用数据类型的数组
2、中间方法
Stream<T> filter(Predicate<? super T>predicate);//过滤
Stream<T>limit(long maxSize);//获取前几元素
Stream<T>skip(long n);//跳过前几个元素
Stream<T> distinct();//元素去重,依赖(hashCode和equals方法)
static <T>Stream<T>concat(Stream a,Stream b);//合并a和b两个流为以个流
Stream<R> map(Function<T,R> mapper);//转换流中的数据类型
注意:
1、中间方法返回一个新的stream流,原本的stream流只能使用一次,建议是用链式编程。
2、修改Stream流中的数据,不会影响原来集合或数组中的数据。
3、终结方法
void forEach(Consumer action);//遍历
Long count();//统计
toArray();//收集流中的数据,放到数组中
collect(Collector collector);//收集流中的数据放到集合中
方法引用
把已有的方法拿过来用,当作函数式接口中抽象方法的方法体。
要求:
1、引用处必须是函数式接口
2、被引用的方法必须已经存在
3、被引用的方法的形参和返回值必须和抽象方法一致
4、被引用的方法要满足当前的需求
分类:
1、引用静态方法
格式:类名::方法
例:Integer::parseInt();
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list,"1","2","3","4");
list.stream().map(Integer::parseInt).forEach(s-> System.out.println(s));
2、引用成员方法
对象::成员方法;
1、其他类:其他类对象::方法名;
2、本类:this::方法名;//不能在静态方法中使用
3、父类:super::方法名;//不能在静态方法中使用
3、引用构造方法
类名::new;
例:Student::new;
4、类名引用成员方法
类名::方法名;
要求:
1、引用处必须是函数式接口
2、被引用的方法必须已经存在
3、被引用的方法的形参,需要跟抽象方法的第二个到最后一个形参一致,返回值需要保持一致
4、被引用的方法要满足当前的需求
局限性:
不能引用所有类中的方法
是跟抽象方法的第一个参数有关,这个参数是什么类型的,就只能引用这个类中的方法。
5、引用数组的构造方法
数据类型[]::new;
例:int[]::new;
ArrayList<Integer> list = new ArrayList<>();
Collections.addAll(list,1,2,3,4,5);
intlist.stream().toArray(Integer[]::new);