目录
Lambda表达式
- 标准格式
- 组成
- 一些参数
- 一个箭头
- 一段代码
2.格式:(参数列表) -> {重写方法的代码}
3.解释说明格式:
():接口中抽象方法中的参数列表,无参就空着,多个参数逗号分隔
->:将参数传递给方法体{}
Thread thread = new Thread(() -> System.out.println("用Lambda创建一个线程"));
函数式接口
- 使用Lambda表达式必须要满足是在函数式接口中
- 一个接口仅有一个抽象方法
- 可用@FunctionalInterface注解检测该接口是否为一个函数式接口
Stream流简介
Stream是Java8中处理集合的关键抽象概念,Stream API提供了一种高效且易于使用的处理数据的方式。你可以使用它对集合数据进行指定操作,如可以执行非常复杂的查找、过滤和映射数据等操作。
Stream(流)是一个来自数据源的元素队列并支持聚合操作
- 元素是特定类型的对象,形成一个队列。 Java中的Stream并不会存储元素,而是按需计算。
- 数据源 流的来源。 可以是集合,数组,I/O channel, 产生器generator 等。
- 聚合操作 类似SQL语句一样的操作, 比如filter, map, reduce, find, match, sorted等。
和以前的Collection操作不同, Stream操作还有两个基础的特征:
- Pipelining: 中间操作都会返回流对象本身。 这样多个操作可以串联成一个管道, 如同流式风格(fluent style)。 这样做可以对操作进行优化, 比如延迟执行(laziness)和短路( short-circuiting)。
- 内部迭代: 以前对集合遍历都是通过Iterator或者For-Each的方式, 显式的在集合外部进行迭代, 这叫做外部迭代。 Stream提供了内部迭代的方式, 通过访问者模式(Visitor)实现。
注意:
Stream自己不会存储元素
Stream不会改变源对象,Stream操作会返回一个新的Stream
Stream操作是延迟执行的,这意味着等到获取结果时,Stream才会执行
Stream操作的三个步骤:
Stream创建,由一个数据源,如集合、数组来获取一个Stream
中间操作。一个中间操作链,对数据源的数据进行处理
终止操作。执行中间操作链并产生结果。
Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。
这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。
元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。
生成流
在 Java 8 中, 集合接口有两个方法来生成流:
-
stream() − 为集合创建串行流。
-
parallelStream() − 为集合创建并行流。
List<String> apples = appleStores.stream()
.filter(apple -> apple.getColor().equals("red"))
.map(apple -> apple.getOrigin())
.sorted()
.limit(3)
.collect(Collectors.toList());
stream:将集合转换成流
filter:将appleStores中颜色为”red”的元素过滤出来
map:将原来的List<AppleStores>转换为List<String>,其中的String元素为AppleStores中的origin成员变量
sorted:排序
limit:只保留前10个元素
collect:将流转换回集合类型
根据Collection获取流
public static void main(String[] args) {
List<String> list = new ArrayList<>();
Stream<String> stream1 = list.stream();
Set<String> set = new HashSet<>();
Stream<String> stream2 = set.stream();
Vector<String> vector = new Vector<>();
// ...
}
根据Map获取流
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
Stream<String> keyStream = map.keySet().stream();
Stream<String> valueStream = map.values().stream();
Stream<Map.Entry<String, String>> entryStream = map.entrySet().stream();
}
根据数组获取流
如果使用的不是集合或映射而是数组,由于数组对象不可能添加默认方法,所以 Stream 接口中提供了静态方法of ,使用很简单:
public static void main(String[] args) {
//使用 Stream.of
String[] array = { "张无忌", "张翠山", "张三丰", "张一元" };
Stream<String> stream = Stream.of(array);
//使用Arrays的静态方法
Arrays.stream(array)
}
Stream的中间操作
新建一个测试使用的Person实体类:
@Data
@AllArgsConstructor
public class Person {
private int id;
private String name;
private int age;
private String country;
}
filter方法:
- 接收Lambda,从流中排除某些元素(过滤)
- 将一个流转换成另一个子集流。
public static void main(String[] args) {
List<Person> peoples = Arrays.asList(
new Person(3, "张三", 18, "中国"),
new Person(2, "王五", 70, "中国"),
new Person(1, "JACK", 39, "美国"),
new Person(4, "MOLLY", 56, "英国"),
new Person(6, "田七", 22, "中国"),
new Person(5, "麦克", 31, "美国")
);
/**
* filter方法——接收Lambda,从流中排除某些元素
* 过滤出country为“中国”的元素
*/
peoples.stream().filter(person -> person.getCountry().equals("中国")).forEach(item-> System.out.println(item));
/**
* 输出结果:
* Person(id=3, name=张三, age=18, country=中国)
* Person(id=2, name=王五, age=70, country=中国)
* Person(id=6, name=田七, age=22, country=中国)
*/
}
map方法:
- 接收Lambda,将元素转化成其他形式或提取信息。接收一个函数作为参数, 该函数会被应用到每个元素上,并将其映射成一个新的元素
public static void main(String[] args) {
List<Person> peoples = Arrays.asList(
new Person(3, "张三", 18, "中国"),
new Person(2, "王五", 70, "中国"),
new Person(1, "JACK", 39, "美国"),
new Person(4, "MOLLY", 56, "英国"),
new Person(6, "田七", 22, "中国"),
new Person(5, "麦克", 31, "美国")
);
/**
* 把stream流中的对象全部转成String类型,为persons数组每一个元素的name
*/
List<String> list = peoples.stream().map(person -> person.getName()).collect(Collectors.toList());
list.forEach(item -> System.out.println(item));
/**
* 输出结果:
* 张三
* 王五
* JACK
* MOLLY
* 田七
* 麦克
*/
}
limit方法:
- 截断流,使其元素不超过给定数量
public static void main(String[] args) {
List<Person> peoples = Arrays.asList(
new Person(3, "张三", 18, "中国"),
new Person(2, "王五", 70, "中国"),
new Person(1, "JACK", 39, "美国"),
new Person(4, "MOLLY", 56, "英国"),
new Person(6, "田七", 22, "中国"),
new Person(5, "麦克", 31, "美国")
);
/**
* 只返回Stream中前3个元素
*/
List<Person> list = peoples.stream().limit(3).collect(Collectors.toList());
list.forEach(person -> System.out.println(person));
/**
* 输出结果:
* Person(id=3, name=张三, age=18, country=中国)
* Person(id=2, name=王五, age=70, country=中国)
* Person(id=1, name=JACK, age=39, country=美国)
*/
}
skip方法:
- 如果希望跳过前几个元素,可以使用 skip 方法获取一个截取之后的新流
- 如果流的当前长度大于n,则跳过前n个;否则将会得到一个长度为0的空流
public static void main(String[] args) {
List<Person> peoples = Arrays.asList(
new Person(3, "张三", 18, "中国"),
new Person(2, "王五", 70, "中国"),
new Person(1, "JACK", 39, "美国"),
new Person(4, "MOLLY", 56, "英国"),
new Person(6, "田七", 22, "中国"),
new Person(5, "麦克", 31, "美国")
);
/**
* 跳过前两个元素
*/
List<Person> list = peoples.stream().skip(2).collect(Collectors.toList());
list.forEach(item -> System.out.println(item));
/**
* 输出结果:
* Person(id=1, name=JACK, age=39, country=美国)
* Person(id=4, name=MOLLY, age=56, country=英国)
* Person(id=6, name=田七, age=22, country=中国)
* Person(id=5, name=麦克, age=31, country=美国)
*/
/**
* 跳过前10个元素,如果超过当前流的长度则会返回空流
*/
List<Person> list1 = peoples.stream().skip(10).collect(Collectors.toList());
list1.forEach(item -> System.out.println(item));
/**
* 无输出
*/
}
sorted 方法:
-
sorted():自然排序
-
sorted(Comparator com):定制排序
public static void main(String[] args) {
List<Person> peoples = Arrays.asList(
new Person(3, "张三", 18, "中国"),
new Person(2, "王五", 70, "中国"),
new Person(1, "JACK", 39, "美国"),
new Person(4, "MOLLY", 56, "英国"),
new Person(6, "田七", 22, "中国"),
new Person(5, "麦克", 31, "美国")
);
/**
* 按照id升序
* 用sorted() 自然排序
*/
List<Person> list= peoples.stream().sorted(Comparator.comparingInt(Person::getId)).collect(Collectors.toList());
list.forEach(item -> System.out.println(item));
/**
* 输出结果
* Person(id=1, name=JACK, age=39, country=美国)
* Person(id=2, name=王五, age=70, country=中国)
* Person(id=3, name=张三, age=18, country=中国)
* Person(id=4, name=MOLLY, age=56, country=英国)
* Person(id=5, name=麦克, age=31, country=美国)
* Person(id=6, name=田七, age=22, country=中国)
*/
/**
* 按照id降序
* 用sorted(Comparator com)定制排序
*/
List<Person> list1= peoples.stream()
.sorted((p1,p2) -> p2.getId() - p1.getId())
.collect(Collectors.toList());
list1.forEach(System.out::println);
/**
* 输出结果:
* Person(id=6, name=田七, age=22, country=中国)
* Person(id=5, name=麦克, age=31, country=美国)
* Person(id=4, name=MOLLY, age=56, country=英国)
* Person(id=3, name=张三, age=18, country=中国)
* Person(id=2, name=王五, age=70, country=中国)
* Person(id=1, name=JACK, age=39, country=美国)
*/
}
concat组合流(终结方法):
- 将两个流合并成一个流
public static void main(String[] args) {
List<Person> peoples = Arrays.asList(
new Person(3, "张三", 18, "中国"),
new Person(2, "王五", 70, "中国"),
new Person(1, "JACK", 39, "美国"),
new Person(4, "MOLLY", 56, "英国"),
new Person(6, "田七", 22, "中国"),
new Person(5, "麦克", 31, "美国")
);
/**
* 将两个流合并
*/
Stream<Person> peoples1 = Arrays.asList(
new Person(8, "猪猪", 23, "中国"),
new Person(7, "EF", 50, "中国")
).stream();
Stream<Person> list = Stream.concat(peoples.stream(), peoples1);
list.forEach(item -> System.out.println(item));
/**
* 输出结果:
* Person(id=3, name=张三, age=18, country=中国)
* Person(id=2, name=王五, age=70, country=中国)
* Person(id=1, name=JACK, age=39, country=美国)
* Person(id=4, name=MOLLY, age=56, country=英国)
* Person(id=6, name=田七, age=22, country=中国)
* Person(id=5, name=麦克, age=31, country=美国)
* Person(id=8, name=猪猪, age=23, country=中国)
* Person(id=7, name=EF, age=50, country=中国)
*/
}
distinct方法:
- 去除流中重复的元素(使用hashcode和equals方法来对比)
public static void main(String[] args) {
List<Person> peoples = Arrays.asList(
new Person(3, "张三", 18, "中国"),
new Person(2, "王五", 70, "中国"),
new Person(1, "JACK", 39, "美国"),
new Person(1, "JACK", 39, "美国"),
new Person(4, "MOLLY", 56, "英国"),
new Person(6, "田七", 22, "中国"),
new Person(6, "田七", 22, "中国"),
new Person(5, "麦克", 31, "美国"),
new Person(5, "麦克", 31, "美国")
);
/**
* 去除流中重复的元素
* 使用hashcode和equals方法来对比
*/
List<Person> list = peoples.stream().distinct().collect(Collectors.toList());
list.forEach(item -> System.out.println(item));
/**
* 输出结果
* Person(id=3, name=张三, age=18, country=中国)
* Person(id=2, name=王五, age=70, country=中国)
* Person(id=1, name=JACK, age=39, country=美国)
* Person(id=4, name=MOLLY, age=56, country=英国)
* Person(id=6, name=田七, age=22, country=中国)
* Person(id=5, name=麦克, age=31, country=美国)
*/
}
检测匹配(终结方法):
- allMatch:是否全部匹配(返回Boolean值)
- anyMatch:是否至少匹配一个(返回Boolean值)
- noneMatch:是否没有匹配的(返回Boolean值)
public static void main(String[] args) {
List<Person> peoples = Arrays.asList(
new Person(3, "张三", 18, "中国"),
new Person(2, "王五", 70, "中国"),
new Person(1, "JACK", 39, "美国"),
new Person(1, "JACK", 39, "美国"),
new Person(4, "MOLLY", 56, "英国"),
new Person(6, "田七", 22, "中国"),
new Person(6, "田七", 22, "中国"),
new Person(5, "麦克", 31, "美国"),
new Person(5, "麦克", 31, "美国")
);
/**
* 判断流中是否每个元素的country都是“中国”
*/
boolean a = peoples.stream().allMatch(person -> person.getCountry().equals("中国"));
System.out.println(a); //结果:false
/**
* 判断流中是否至少有一个元素的country是“中国”
*/
boolean b = peoples.stream().anyMatch(person -> person.getCountry().equals("中国"));
System.out.println(b); //结果:true
/**
* 判断流中的元素是否没有age大于71的
*/
boolean c = peoples.stream().noneMatch(person -> person.getAge() > 71);
System.out.println(c); //结果:true
}
count方法(终结方法):
- 计算流中元素的个数
- 返回一个Long值
public static void main(String[] args) {
List<Person> peoples = Arrays.asList(
new Person(3, "张三", 18, "中国"),
new Person(2, "王五", 70, "中国"),
new Person(1, "JACK", 39, "美国"),
new Person(1, "JACK", 39, "美国"),
new Person(4, "MOLLY", 56, "英国"),
new Person(6, "田七", 22, "中国"),
new Person(6, "田七", 22, "中国"),
new Person(5, "麦克", 31, "美国"),
new Person(5, "麦克", 31, "美国")
);
/**
* 得到流中元素的个数
*/
long count = peoples.stream().count();
System.out.println(count); // 结果:6
}
规约(终结方法):
- reduce(T identity,BinaryOperator):可以将流中元素反复结合起来,得到一个值,返回T
- reduce(BinaryOperator):可以将流中元素反复结合起来,得到一个值,返回Optionnal<T>
- 其中 identity 为初始值
public static void main(String[] args) {
List<Person> peoples = Arrays.asList(
new Person(3, "张三", 18, "中国"),
new Person(2, "王五", 70, "中国"),
new Person(1, "JACK", 39, "美国"),
new Person(1, "JACK", 39, "美国"),
new Person(4, "MOLLY", 56, "英国"),
new Person(6, "田七", 22, "中国"),
new Person(6, "田七", 22, "中国"),
new Person(5, "麦克", 31, "美国"),
new Person(5, "麦克", 31, "美国")
);
/**
* 将所有元素的age累加
* 先将流中所有元素的age映射出来
*/
Integer count = peoples.stream()
.map(Person::getAge)
.reduce(0, (age1, age2) -> age1 + age2);
System.out.println(count); // 结果:236
/**
* 将所有元素的age累加求平均值
* 先将流中所有元素的age映射出来
*/
Optional<Integer> count1 = peoples.stream()
.map(Person::getAge)
.reduce(Integer::sum);
long peopleCount = peoples.stream().count();
System.out.println(count1.get() / peopleCount); // 结果:39
}
收集(终结方法):
- collect(Collector c):将流转化为其他形式,接收一个Collector接口的实现
public static void main(String[] args) {
List<Person> peoples = Arrays.asList(
new Person(3, "张三", 18, "中国"),
new Person(2, "王五", 70, "中国"),
new Person(1, "JACK", 39, "美国"),
new Person(1, "JACK", 39, "美国"),
new Person(4, "MOLLY", 56, "英国"),
new Person(6, "田七", 22, "中国"),
new Person(6, "田七", 22, "中国"),
new Person(5, "麦克", 31, "美国"),
new Person(5, "麦克", 31, "美国")
);
/**
* collect:收集
* 1.收集age大于30的元素,转成一个List集合
*/
List<Person> list = peoples.stream()
.filter(person -> person.getAge() > 30)
.collect(Collectors.toList()); // 将流转换回List
list.forEach(item -> System.out.println(item));
/**
* 输出结果:
* Person(id=2, name=王五, age=70, country=中国)
* Person(id=1, name=JACK, age=39, country=美国)
* Person(id=4, name=MOLLY, age=56, country=英国)
* Person(id=5, name=麦克, age=31, country=美国)
*/
/**
* 收集country为“中国”的元素转换成set集合
*/
Set<Person> set = peoples.stream()
.filter(person -> person.getCountry().equals("中国"))
.collect(Collectors.toSet()); // 将流转换成set
System.out.println(set);
/**
* 输出结果:
* [Person(id=6, name=田七, age=22, country=中国),
* Person(id=2, name=王五, age=70, country=中国),
* Person(id=3, name=张三, age=18, country=中国)]
*/
}
迭代:
- 可以使用Stream.iterate创建流值,即所谓的无限流
Stream.iterate(0,n->n+1).limit(5).forEach(num -> System.out.println(num));
/**
* 输出结果:
* 0
* 1
* 2
* 3
* 4
*/
练习:
递归生成三级分类树:
@Override
public List<CategoryEntity> listWithTree() {
// 1.查出所有分类
List<CategoryEntity> entities = categoryDao.selectList(null);
// 2.组装出父子的树形结构
// 2.1)、找出所有一级分类
return entities.stream()
.filter(categoryEntity ->categoryEntity.getParentCid() == 0)
.map((menu)->{
menu.setChildren(getChildrens(menu,entities) );
return menu;
}).sorted((menu1,menu2)->{
return (menu1.getSort()==null?0:menu1.getSort()) - (menu2.getSort()==null?0:menu2.getSort());
}).collect(Collectors.toList());
}
// 递归查找所有菜单的子菜单
public List<CategoryEntity> getChildrens(CategoryEntity root,List<CategoryEntity> all ){
List<CategoryEntity> list = all.stream().filter(categoryEntity -> categoryEntity.getParentCid() == root.getCatId())
.map(CategoryEntity -> {
CategoryEntity.setChildren(getChildrens(CategoryEntity, all));
return CategoryEntity;
}).sorted((menu1, menu2) -> {
return (menu1.getSort()==null?0:menu1.getSort()) - (menu2.getSort()==null?0:menu2.getSort());
})
.collect(Collectors.toList());
return list;
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/154457.html