Stream是JDK8 API的新成员,它允许以声明性方式处理数据集合.
1 特点:
1 代码简洁: 函数式编程写出的代码简洁且意图明确,使用Stream接口让你从此告别for循环
2 多核友好: java函数式编程使得编写并行程序从未如此简单,你需要的全部就是调用一下方法.
2 流程:
第一步: 把集合转为stram流
第二步: 操作stream流
stream流在管道中经过中间操作,(intermediate operation) 的处理,最终操作(terminal operation)得到前面处理的结果
3 操作符
两种:中间操作符,终止操作符
4 详情
1 生成流
- stream() − 为集合创建串行流
- parallelStream() − 为集合创建并行流
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
2 中间操作符
filter 过滤集合中不符合条件的元素
/**
* filter过滤集合中不符合条件的元素
*/
@Test
public void filter() {
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd");
//集合转成流
//方式一 list.stream
List<String> filter = strings.stream().filter(str -> str.contains("f")).collect(Collectors.toList());
System.out.println(filter);
}
distinct 去重集合中元素
/**
* 去重集合中元素
*/
@Test
public void distinct() {
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd", "abc", "bc");
System.out.println(strings);
//去重元素
List<String> filter = strings.stream().distinct().collect(Collectors.toList());
System.out.println(filter);
//------------------------------------------------
去重对象 对象的地址不一样,即使内容一样,也不能去重.
解决: 需要重写对象的equals和hashcode方法
}
limit 获取流中前几个元素
/**
* 获取流中前几个元素
*/
@Test
public void limit() {
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd");
//集合转成流
List<String> filter = strings.stream().limit(2).collect(Collectors.toList());
System.out.println(filter);
}
skip 获取流中除去前n个元素
/**
* 获取流中除去前n个元素
*/
@Test
public void skip() {
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd");
//集合转成流
List<String> filter = strings.stream().skip(2).collect(Collectors.toList());
System.out.println(filter);
}
map 对流中所有元素统一处理
/**
* 对流中所有元素统一处理
*/
@Test
public void map() {
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd");
//集合转成流
List<String> filter = strings.stream().map(str -> str.concat("11")).collect(Collectors.toList());
System.out.println(filter);
}
flatmap 对流中所有元素,进行扁平化处理
/**
* 对流中所有元素 进行扁平化处理
*/
@Test
public void flatmap() {
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd");
//集合转成流
/**
* 解析flatmap
* 1 [a,b,c] [b,c]
* 2 扁平化操作 [a,b,c,b,c]
*/
List<Character> list = strings.stream().flatMap(str -> demo.getCharacterByStrinng(str)).collect(Collectors.toList());
System.out.println(list);
}
/**
* 字符串转换为字符流
*
* @param str
* @return
*/
public static Stream<Character> getCharacterByStrinng(String str) {
List<Character> characterList = new ArrayList<>();
for (Character user : str.toCharArray()) {
characterList.add(user);
}
return characterList.stream();
}
sorted 排序
/**
* 排序
*/
@Test
public void sorted() {
// List<String> strings = new ArrayList<>();
List<String> strings = Arrays.asList("abc", "b", "bc", "efg", "abcd");
//集合转成流
//默认排序 按照字符排序
List<String> list = strings.stream().sorted().collect(Collectors.toList());
System.out.println(list);
//-----------------数字排序---------------------
List<Integer> list1 = Arrays.asList(12, 1, 23, 234, 24);
list1.stream().sorted().collect(Collectors.toList()).forEach(s -> System.out.println(s));
//-------------------汉字排序-------------------
//需要添加jar包
// <!--apache集合操作工具包-->
// <dependency>
// <groupId>org.apache.commons</groupId>
// <artifactId>commons-collections4</artifactId>
// <version>4.3</version>
// </dependency>
List<String> list2 = Arrays.asList("张三", "赵柳", "王五", "李四", "李哥");
list2.stream().sorted(Collator.getInstance(Locale.CANADA)).collect(Collectors.toList()).forEach(System.out::println);
}
3终止操作符
anyMatch
/**
* 集合中是否有一个元素满足条件
*/
@Test
public void anyMatch() {
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd");
boolean a = strings.stream().anyMatch(s -> s.contains("a"));
System.out.println(a);
}
allMatch
/**
* 集合中是否都满足条件
*/
@Test
public void allMatch() {
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd");
boolean a = strings.stream().allMatch(s -> s.contains("a"));
System.out.println(a);
}
noneMatch
/**
* 集合中是否都不满足条件
*/
@Test
public void noneMatch() {
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd");
boolean a = strings.stream().noneMatch(s -> s.contains("a"));
System.out.println(a);
}
findAll
/**
* 返回集合中任意元素
*/
@Test
public void findAll() {
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd");
Optional<String> any = strings.stream().findAny();
if (any.isPresent()) System.out.println(any.get());
}
findFirst
/**
* 返回集合中第一个元素
*/
@Test
public void findFirst() {
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd");
Optional<String> any = strings.stream().findFirst();
if (any.isPresent()) System.out.println(any.get());
}
forEach
/**
* 遍历 循环
*/
@Test
public void forEach() {
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd");
strings.stream().forEach(s -> System.out.println(s));
}
collect
/**
* 收集器,将流转换为其他形式
*/
@Test
public void collect() {
List<String> strings = Arrays.asList("abc", "abc", "bc", "efg", "abcd");
//list set map
Set<String> collect = strings.stream().collect(Collectors.toSet());
System.out.println(collect);
//-----------------------------map------------------
//下面方式 集合中允许有重复的元素
Map<String, String> collect1 = strings.stream().collect(Collectors.toMap(v -> "pro_" + v, v -> v, (oldvalue, newvalue) -> newvalue));
//下面方式 集合中不能有重复的元素
// Map<String, String> collect1 = strings.stream().collect(Collectors.toMap(v -> "pro_"+v, v -> v));
System.out.println(collect1);
}
reduce
/**
* 将流中数据反复结合起来得到一个结果
*/
@Test
public void reduce() {
List<String> strings = Arrays.asList("abc", "abc", "bc", "efg", "abcd");
Optional<String> reduce = strings.stream().reduce((acc, item) -> {
//反复结合起来得到结果
// return acc+item;
//将结果进行处理 如去掉里面a字符串
return (acc + item).replace("a", "");
});
if (reduce.isPresent())
System.out.println(reduce.get());
}
count
/**
* 返回集合中元素数量
*/
@Test
public void count() {
List<String> strings = Arrays.asList("abc", "abc", "bc", "efg", "abcd");
long count = strings.stream().count();
System.out.println(count);
}
5 经典案列
需求: 父子部门的封装
@Test
public void testtree(){
//模拟从数据库查询出来
List<Menu> menus = Arrays.asList(
new Menu(1,"根节点",0),
new Menu(2,"子节点1",1),
new Menu(3,"子节点1.1",2),
new Menu(4,"子节点1.2",2),
new Menu(5,"根节点1.3",2),
new Menu(6,"根节点2",1),
new Menu(7,"根节点2.1",6),
new Menu(8,"根节点2.2",6),
new Menu(9,"根节点2.2.1",7),
new Menu(10,"根节点2.2.2",7),
new Menu(11,"根节点3",1),
new Menu(12,"根节点3.1",11),
new Menu(12,"根节点3.1",11)
);
//得到所有的id
//此处有问题, 如果想得到一个父节点下所有子节点,则该方法不行
List<Integer> collect1 = menus.stream()
.distinct()
.map(str -> str.getId())
.collect(Collectors.toList());
System.out.println(collect1);
System.out.println("====================================");
System.out.println(JSON.toJSON(menus));
System.out.println("====================================");
//获取父节点
List<Menu> collect = menus.stream().filter(m -> m.getParentId() == 0).map(
(m) -> {
m.setChildList(getChildrens(m, menus));
return m;
}
).collect(Collectors.toList());
System.out.println("-------转json输出结果-------");
System.out.println(JSON.toJSON(collect));
}
/**
* 递归查询子节点
* @param root 根节点
* @param all 所有节点
* @return 根节点信息
*/
private List<Menu> getChildrens(Menu root, List<Menu> all) {
List<Menu> children = all.stream().filter(m -> {
return Objects.equals(m.getParentId(), root.getId());
}).map(
(m) -> {
m.setChildList(getChildrens(m, all));
return m;
}
).collect(Collectors.toList());
return children;
}