Lambda 表达式
可以对某些匿名内部类的写法进行简化,让我们不用关注是什么对象,而是更关注我们对数据进行了什么操作。
核心原则:可推导可省略
基本格式:(参数列表)-> {代码}
关注的是参数列表和具体的逻辑代码体
省略规则:
-
参数类型可以省略
-
方法体中只有一句代码时大括号return和唯一一句代码的分号可以省略
-
方法只有一个参数时小括号可以省略
-
如果能简化成lambda 有快捷键:光标放在匿名内部类上面 Alt+回车(最简化的)
public static void main(String[] args) { //匿名内部类 Num(new IntBinaryOperator() { @Override public int applyAsInt(int left, int right) { return left + right; } }); //lambda表达式 Num(( i,j) ->//参数类型可以省略 i + j //方法体中只有一句代码时,大括号return和唯一一句代码的分号可以省略 ); } /** * 例子1 */ public static int Num(IntBinaryOperator operator){ int a = 20; int b = 30; return operator.applyAsInt(a,b); }
Stream流
Java 8的stream使用的是函数式编程模式,可以被用来对集合或数组进行链状流式的操作,可以更方便的让我们对集合或数组进行操作。
注意事项:
-
惰性求职(如果没有终结操作,中间操作是不会执行的)
-
流是一次性的(一旦一个流对象经过一个终结操作之后。这个流就不能再被使用)
-
不会影响原始数据(我们在流中可以对数据做很多处理。但是正常情况下是不会影响原来集合中的元素的。)
常用操作:
1.创建流
1.1单列集合
//单例集合 集合对象.stream() List<Book> list = new ArrayList<>(); Stream<Book> stream = list.stream();
1.2数组
//数组:Arrays.stream(数组)或者Stream.of(数组) Integer[] arr = {1,2,3}; Stream<Integer> stream1 = Arrays.stream(arr); Stream<Integer> stream2 = Stream.of(arr);
1.3双列集合
//双列集合:转换成单列后在创建 Map<String,Object> map = new HashMap<>(); map.put("aaa",11); //entrySet():装换成Set集合 Set<Map.Entry<String, Object>> set = map.entrySet(); Stream<Map.Entry<String, Object>> stream3 = set.stream();
2.中间操作
2.1 filter
可以对流中元素进行条件过滤,符合条件的才能继续留在流中
//查询集合中名字长度大于2的名字 stream.filter(book -> book.getName().length()>=2) .forEach(book -> System.out.println(book.getName()));
2.2 map
可以对流中元素进行计算或转换
//把集合中的所有分数+10 stream.map(book -> book.getScore()) .map(s->s+10) .forEach(s-> System.out.println(s));
2.3 distinct
可以去除流中的重复元素
注意:distinct方法是依赖Object的equals方法判断是否是相同对象的。所以需要注意重写equals方法。(实体类添加 @EqualsAndHashCode 注解)
//查询集合中的名字,要求不能重复(整个对象的所有值相同才算重复,就单独名字相同不算重复) list.stream() .distinct() .forEach(book-> System.out.println(book.getName()));
2.4 sorted
可以对流中的元素进行排序
如果调用空参的sorted()方法,实体类要实现Comparable类
//想要有比较能力 比如排序 就要实现Comparable类 public class Book implements Comparable<Book>
@Override public int compareTo(Book o) { //改变这两个的位置可以调整降序还是升序 return o.getScore()- this.getScore(); }
//根据分数降序排序,要求不能有重复的元素 list.stream() .distinct() //调用无参方法 .sorted() .forEach(book-> System.out.println(book.getScore()));
//匿名内部类方法可直接使用 .sorted(new Comparator<Book>() { @Override public int compare(Book o1, Book o2) { return o1.getScore()- o2.getScore(); } })
2.5 limit
可以设置流的最大长度,超出的部分将被舍弃
//根据分数降序排序,要求不能有重复的元素,输出分数最高的两个 list.stream() .distinct() .sorted() .limit(2) .forEach(book-> System.out.println(book.getScore()));
2.6 skip
可以跳过流中的前n个元素,返回剩下的元素
//根据分数降序排序,要求不能有重复的元素,分数最高的不要输出 list.stream() .distinct() .sorted() .skip(1) .forEach(book-> System.out.println(book.getName()));
2.7 flatMap
map操作只能把一个对象转换成另一个对象来作为流当中的元素,而flatMap操作可以把一个对象转换成多个对象作为流中的元素。
//打印所有书籍的名字,对重复的元素进行去重(有多个作家,每个作家又有多本书) authorList.stream() .flatMap(author -> author.getBooks().stream()) .distinct() .forEach(book -> System.out.println(book.getName()));
//打印所有书籍的分类,对分类进行去重,不能出现这种格式(历史,散文) getAuthors().stream() .flatMap(author -> author.getBooks().stream()) .distinct() //book.getCategory().split(","):逗号分隔的字符串数组 //数组转换成stream流 Arrays.stream(arr)或者Stream.of(arr) .flatMap(book -> Stream.of(book.getCategory().split(","))) .distinct() .forEach(s-> System.out.println(s));
3.终结操作(必须有终结操作,流才会被使用)
3.1 foreach
对流中元素进行遍历操作,我们通过传入的参数去指定对遍历的元素进行什么具体操作。
//输出所有作家的名字 getAuthors().stream() .forEach(author -> System.out.println(author.getName()));
3.2 count
可以用来获取当前流中元素的个数
注意:count会返回一个Long类型的结果,所以要接收一下才能输出。
//输出所有作家所出版的书籍数目,删除重复元素 long count = getAuthors().stream() .flatMap(author -> author.getBooks().stream()) .distinct() .count(); System.out.println(count);
3.3 max&min
可以获取流中的最值
//输出所有作家所出版的书籍中得最高分和最低分 Optional<Integer> min = getAuthors().stream() .flatMap(author -> author.getBooks().stream()) .map(book -> book.getScore()) .min((o1, o2) -> o1 - o2); //终结操作之后就不能在.了 Optional<Integer> max = getAuthors().stream() .flatMap(author -> author.getBooks().stream()) .map(book -> book.getScore()) .max((o1, o2) -> o1 - o2); System.out.println("最小:"+min.get()+" 最大:"+max.get());
3.4 collect
可以把当前流转换成一个集合
//获取一个存放所有记者名字的 List集合 List<String> list = getAuthors().stream() .map(author -> author.getName()) .collect(Collectors.toList()); System.out.println(list); //获取一个存放所有书籍名字的 Set集合 Set<String> set = getAuthors().stream() .flatMap(author -> author.getBooks().stream()) .map(book -> book.getName()) .collect(Collectors.toSet()); System.out.println(set); //获取一个Map集合,key为作者名字,values为List<books> Map<String, List<Book>> map = getAuthors().stream() .distinct() .collect(Collectors.toMap(author -> author.getName(), author -> author.getBooks()));
3.5 查找和匹配
3.5.1 anyMatch
可以用来判断流中是否有任意符合匹配条件的元素,结果为boolean类型。
元素有一个满足即可。
//判断是否有年龄在29岁以上的作家 boolean b = getAuthors().stream() .anyMatch(author -> author.getAge() > 29); System.out.println(b);
3.5.2 allMath
可以用来判断流中是否都符合匹配条件,结果为boolean类型,都符合返回t反之返回f。
必须所有元素都满足。
//判断是否所有作家都是成年人 boolean b = getAuthors().stream() .allMatch(author -> author.getAge() < 18); System.out.println(b);
3.5.3 noneMatch
可以用来判断流中是否都不符合匹配条件,结果为boolean类型,都不符合返回t反之返回f。
必须所有元素都不满足。
//判断是否所有作家都没有100岁的 boolean b = getAuthors().stream() .noneMatch(author -> author.getAge() > 100); System.out.println(b);
3.5.4 findAny
获取流中的任意一个元素,该方法没有办法保证获取的一定是流中的第一个元素。
//输出一个年龄小于50的作家姓名 Optional<Author> any = getAuthors().stream() .filter(author -> author.getAge() < 50) .findAny(); System.out.println(any.get().getName());
3.5.5 findFirst
获取流中的第一个元素
//输出年龄最小的作家姓名 Optional<Author> first = getAuthors().stream() .sorted((o1, o2) -> o1.getAge() - o2.getAge()) .findFirst(); System.out.println("年龄最小的是"+first.get().getName());