Stream 流式计算是在jdk 1.8后引入的新特性,将集合或数组 转换成一种流的元素序列。流不是集合中的元素,也不是一种数据结构,不负责数据的存储。Stream 流也不会改变源对象(源集合)
Stream 接口中几乎所有方法的参数都是四大函数式接口接口类型的参数。而函数式接口可以使用 lambda 表达式来简化开发,并且 Stream 接口中的方法基本都是返回对象本身(返回对象本身的方法可以使用链式编程)。所以在使用 Stream 流式计算时,基本上都用到了函数式接口、lambda表达式 和 链式编程。
集合
转换成流
Collection接口在 jdk 1.8 后新增了一个 stream() 方法,调用该方法会得到一个 Stream 流对象。通过这个对象可以调用 Stream 接口相应的方法对集合进行过滤
、排序
、截断(丢弃)
、截断(获取)
、转换
、遍历
、计数
、拼接
、取最大值
、取最小值
等操作。
public static void main(String[] args) {
// 将数组变成一个列表集合
List<Integer> list = Arrays.asList(12, 25, 4, 17, 3);
// 将集合转换成流
Stream<Integer> stream = list.stream();
// 对流进行计算操作:遍历Stream流,将大于10的元素中,截取前面2个输出
stream.filter((i)->{return i > 10;}).limit(2).forEach(System.out::println);
}
数组
转换成流
Stream 接口也提供了一个 of() 方法,底层基于Arrays.stream() 来将数组转换成流。通过流对象可以调用 Stream 接口相应的方法对集合进行过滤
、排序
、截断(丢弃)
、截断(获取)
、转换
、遍历
、计数
、拼接
、取最大值
、取最小值
等操作。
public static void main(String[] args) {
Integer[] array = {12, 25, 4, 17, 3};
// 将数组转换成流
Stream<Integer> stream = Stream.of(array);
// 对流进行计算操作:遍历Stream流,将大于10的元素中,截取前面2个输出
stream.filter((i)->{return i > 10;}).limit(2).forEach(System.out::println);
}
Collection 集合获取 Stream 流 (通过 Collection 集合的 stream()
方法来获取)
// List集合获取 Stream 流
ArrayList<Integer> list = new ArrayList<>();
Stream<Integer> stream = list.stream();
// 通过 Stream 流对象操作数据 (代码省略 . . .)
// List集合获取 Stream 流
List<Integer> list = Arrays.asList(4, 3, 5, 7, 2);
Stream<Integer> stream = list.stream();
// Set集合获取 Stream 流
HashSet<String> set = new HashSet<>();
Stream<String> stream = set.stream();
// 通过 Stream 流对象操作数据 (代码省略 . . .)
数组获取 Stream 流 (通过 Stream 的 of()
方法来获取,of()
方法的底层通过 工具类Arrays
的stream()
方法来获取)
// 数组获取 Stream 流
Integer[] arr = {4, 3, 5, 7, 2};
Stream<Integer> stream = Stream.of(arr);
// 通过 Stream 流对象操作数据 (代码省略 . . .)
// 数组获取 Stream 流
Stream<Integer> stream = Stream.of(4, 3, 5, 7, 2);
// 通过 Stream 流对象操作数据 (代码省略 . . .)
Stream 流转换成 List 集合(通过 Stream 接口的 collect()
方法来转换)
public static void main(String[] args) {
// 将数组变成一个列表集合
List<Integer> list = Arrays.asList(14, 3, 5, 7, 12);
// List集合获取 Stream 流
Stream<Integer> stream = list.stream();
// 操作 Stream 流
List<Integer> collect = stream
// 获取 > 5 的元素
.filter((i) -> { return i > 5; })
// 对元素进行升序排序
.sorted()
// 将 Stream 流转换成 List 集合
.collect(Collectors.toList());
// 遍历 转换后的 List 集合
for (Integer i : collect) {
System.out.println(i);
}
}
Stream 流转换成 Set 集合(通过 Stream 接口的 collect()
方法来转换)
public static void main(String[] args) {
// 将数组变成一个列表集合
List<Integer> list = Arrays.asList(14, 3, 5, 7, 12);
// List集合获取 Stream 流
Stream<Integer> stream = list.stream();
// 操作 Stream 流
Set<Integer> collect = stream
// 获取 > 5 的元素
.filter((i) -> { return i > 5; })
// 对元素进行升序排序
.sorted()
// 将 Stream 流转换成 Set 集合
.collect(Collectors.toSet());
// 遍历 转换后的 Set 集合
for (Integer i : collect) {
System.out.println(i);
}
}
Stream 流转换成数组(通过 Stream 接口的 toArray()
方法来转换)
public static void main(String[] args) {
// 数组获取 Stream 流
Stream<Integer> stream = Stream.of(14, 3, 5, 7, 12);
// 操作 Stream 流
Integer[] array = stream
// 获取 > 5 的元素
.filter((i) -> { return i > 5; })
// 对元素进行升序排序
.sorted()
// 将 Stream 流转换成 数组
.toArray(Integer[]::new);
// 遍历 转换后的 数组
for (Integer i : array) {
System.out.println(i);
}
}
Stream of(T… values) 数组获取 Stream 流
public static void main(String[] args) {
// 数组获取 Stream 流
Stream<Integer> stream = Stream.of(14, 3, 5, 7, 12);
}
Stream filter(Predicate predicate) 过滤
public static void main(String[] args) {
// 将数组变成一个列表集合
List<Integer> list = Arrays.asList(12, 25, 4, 17, 3);
// 获取 Stream 流对象进行操作
list.stream()
// 过滤(获取大于10的元素)
.filter((i) -> {return i > 10;})
// 遍历
.forEach(System.out::println);
}
Stream sorted(Comparator super T> comparator) 排序
@Data
@NoArgsConstructor
@AllArgsConstructor
class User {
private int id;
private String name;
private int age;
}
public class Test {
public static void main(String[] args) {
ArrayList<User> list = new ArrayList<>();
list.add(new User(1, "王一", 27));
list.add(new User(2, "王二", 23));
list.add(new User(3, "王三", 25));
list.add(new User(4, "王四", 24));
// 获取 Stream 流对象进行操作
list.stream()
// 根据年龄排序
.sorted(Comparator.comparing(User::getAge)) // 升序排序
//等价于: .sorted(Comparator.comparing((user)->{return user.getAge();}))
.sorted(Comparator.comparing(User::getAge).reversed()) // 降序排序
// 遍历
.forEach(System.out::println);
// 获取 Stream 流对象进行操作
list.stream()
// 根据年龄排序
.sorted((c1, c2) -> c1.getAge().compareTo(c2.getAge())) // 升序排序
.sorted((c1, c2) -> c2.getAge().compareTo(c1.getAge())) // 降序排序
.forEach(System.out::println);
}
}
升序排序
public static void main(String[] args) {
// 将数组变成一个列表集合
List<Integer> list = Arrays.asList(5, 3, 7, 9, 4);
// 获取集合的 Stream 流对象
list.stream()
// 升序排序
.sorted()
// 遍历
.forEach(System.out::println);
// 获取集合的 Stream 流对象
list.stream()
// 升序排序
.sorted((c1, c2) -> c1.compareTo(c2))
// 遍历
.forEach(System.out::println);
}
降序排序
public static void main(String[] args) {
// 将数组变成一个列表集合
List<Integer> list = Arrays.asList(5, 3, 7, 9, 4);
// 获取集合的 Stream 流对象
list.stream()
// 降序排序(升序排序的反向排序)
.sorted(Comparator.reverseOrder())
// 遍历
.forEach(System.out::println);
// 获取集合的 Stream 流对象
list.stream()
// 降序排序
.sorted((c1, c2) -> c2.compareTo(c1))
// 遍历
.forEach(System.out::println);
}
多字段排序 (使用Comparator比较器的comparing() 和 thenComparing() 来实现)
@Data
@NoArgsConstructor
@AllArgsConstructor
class User {
private int id;
private String name;
private int age;
}
public class Test {
public static void main(String[] args) {
ArrayList<User> list = new ArrayList<>();
list.add(new User(1, "王一", 27));
list.add(new User(2, "王二", 23));
list.add(new User(3, "王三", 27));
list.add(new User(4, "王四", 24));
// 获取 Stream 流对象进行操作
list.stream()
// 升序排序(先根据年龄排序,如果年龄相同,则年龄相同的用户根据 id 排序)
.sorted(Comparator.comparing(User::getAge).thenComparing(User::getId))
// 遍历
.forEach(System.out::println);
// 获取 Stream 流对象进行操作
list.stream()
// 降序排序(先根据年龄排序,如果年龄相同,则年龄相同的用户根据 id 排序)
.sorted(Comparator.comparing(User::getAge).thenComparing(User::getId).reversed())
// 遍历
.forEach(System.out::println);
}
}
多字段即升序 又 降序排序 (使用Stream的sorted()方法,Comparator比较器的comparing() 和 thenComparing() 作为参数)
@Data
@NoArgsConstructor
@AllArgsConstructor
class User {
private int id;
private String name;
private int age;
}
public class Test {
public static void main(String[] args) {
ArrayList<User> list = new ArrayList<>();
list.add(new User(1, "王一", 27));
list.add(new User(2, "王二", 23));
list.add(new User(3, "王三", 27));
list.add(new User(4, "王四", 24));
// 获取 Stream 流对象进行操作
list.stream()
// 即升序又降序排序(先根据年龄升序排序,如果年龄相同,则年龄相同的用户根据 id 降序排序)
.sorted(Comparator.comparing(User::getAge).thenComparing(User::getId , Comparator.reverseOrder()))
// 遍历
.forEach(System.out::println);
}
}
Stream limit(long maxSize) 截取(截取前面n个元素)
public static void main(String[] args) {
// 将数组变成一个列表集合
List<Integer> list = Arrays.asList(5, 3, 7, 9, 4);
// 获取集合的 Stream 流对象
list.stream()
// 截取(截取前面前4个元素)
.limit(4)
// 遍历
.forEach(System.out::println);
}
Stream skip(long n) 丢弃(丢弃前面n个元素)
public static void main(String[] args) {
// 将数组变成一个列表集合
List<Integer> list = Arrays.asList(5, 3, 7, 9, 4);
// 获取集合的 Stream 流对象
list.stream()
// 丢弃(丢弃前面4个元素)
.skip(4)
// 遍历
.forEach(System.out::println);
}
Stream map(Function super T, ? extends R> mapper) 转换(将 一个 Stream 流 转换成 另一个 Stream 流)
转换流中元素的类型
public static void main(String[] args) {
// 将数组变成一个列表集合
List<Integer> list = Arrays.asList(5, 3, 7, 9, 4);
// 将 Stream 流的 Integer类型 转换成 String类型
Stream<String> stream = list.stream().map(item -> item.toString());
}
对 流 中元素进行运算处理
public static void main(String[] args) {
// 将数组变成一个列表集合
List<Integer> list = Arrays.asList(5, 3, 7, 9, 4);
// 将 Stream 流中元素左移两位,即乘以四
List<Integer> collect = list.stream().map(item -> item << 2).collect(Collectors.toList());
System.out.println(collect.toString());
}
对 流 中元素进行大小写转换
public static void main(String[] args) {
// 将数组变成一个列表集合
List<String> list = Arrays.asList("a", "b", "c", "d", "e");
// 将 Stream 流中全部元素转换成 大写字母
Stream<String> stream = list.stream().map(item -> item.toUpperCase());
}
Stream flatMap(Function super T, ? extends Stream extends R>> mapper)
public static void main(String[] args) {
// 将数组变成一个列表集合
List<String> list = Arrays.asList("hello", "word");
System.out.println(list.toString());
List<String> collect = list.stream()
// 将若干个子管道中的数据,全都展开到父管道中进行处理
.flatMap(item -> Arrays.stream(item.split(""))) // [h,e,l,l,o,w,o,r,l,d]
.collect(Collectors.toList());
System.out.println(collect);
}
void forEach(Consumer super T> action) 遍历(逐个处理流元素)
public static void main(String[] args) {
// 将数组变成一个列表集合
List<Integer> list = Arrays.asList(5, 3, 7, 9, 4);
// 获取集合的 Stream 流对象
list.stream()
// 遍历
.forEach(System.out::println);
}
long count() 计数(返回流中元素个数)
public static void main(String[] args) {
// 将数组变成一个列表集合
List<Integer> list = Arrays.asList(5, 3, 7, 9, 4);
// 获取集合的 Stream 流中元素个数
long count = list.stream().count();
}
Stream concat(Stream extends T> a, Stream extends T> b) 拼接(对两个流对象进行拼接)
public static void main(String[] args) {
// 将数组变成一个列表集合
List<Integer> list_01 = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> list_02 = Arrays.asList(6, 7, 8, 9, 0);
// 将两个 Stream 流拼接(首尾合并),成一个新的 Stream 流
Stream<Integer> stream = Stream.concat(list_01.stream(), list_02.stream());
stream.forEach(System.out::println);
}
Optional max(Comparator super T> comparator) 根据Comparator比较器获取最大的元素
public static void main(String[] args) {
// 将数组变成一个列表集合
List<Integer> list = Arrays.asList(5, 3, 7, 9, 4);
// 获取序列中的值最大的元素
Optional<Integer> max = list.stream().max(Comparator.comparing((integer -> integer)));
System.out.println(max.get());
}
Optional min(Comparator super T> comparator) flatMap 根据Comparator比较器获取最小的元素
public static void main(String[] args) {
// 将数组变成一个列表集合
List<Integer> list = Arrays.asList(5, 3, 7, 9, 4);
// 获取序列中的值最小的元素
Optional<Integer> max = list.stream().min(Comparator.comparing((integer -> integer)));
System.out.println(max.get());
}
Stream distinct() 对 Stream 流中所有元素进行去重,返回新的 Stream 流
public static void main(String[] args) {
// 将数组变成一个列表集合
List<Integer> list = Arrays.asList(5, 3, 7, 5, 4);
// 获取集合的 Stream 流对象
list.stream()
// 相同元素去重
.distinct()
// 遍历
.forEach(System.out::println);
}
普通解题方式:
public static void main(String[] args) {
String[] strArr = {"a", "b", "c", "a", "a", "b", "d"};
HashMap<String, Integer> map = new HashMap<>(8);
for (String s : strArr) {
if(map.containsKey(s)){
map.put(s, map.get(s) + 1);
} else {
map.put(s, 1);
}
}
map.forEach((key, value) -> {System.out.println(key + " : " + value);});
}
Steam 流解题方式:
public static void main(String[] args) {
String[] strArr = {"a", "b", "c", "a", "a", "b", "d"};
Stream.of(strArr)
.collect(Collectors.toMap(key -> key, value -> 1, Integer::sum)) // Integer::sum 等价于 (a, b) -> a + b
.forEach((key, value) -> {System.out.println(key + " : " + value);});
}
public static void main(String[] args) {
String[] strArr = {"a", "d", "c", "d", "d", "b", "a"};
List<Map.Entry<String, Integer>> list = Stream.of(strArr)
// 统计流中相同元素及数量,装成 Map 集合
.collect(Collectors.toMap(key -> key, value -> 1, Integer::sum))
// 将 Map 集合转换成 Set 集合(因为Map集合不能转成Stream流,需要先转成Collection集合后才可以)
.entrySet()
// 将 Set 集合转成 Stream 流
.stream()
// 降序排序
.sorted((c1, c2) -> c2.getValue().compareTo(c1.getValue())) //降序排序
//.sorted((c1, c2) -> c1.getValue().compareTo(c2.getValue())) //升序排序
// 截取前面两个元素
.limit(2)
// 转成 List 集合
.collect(Collectors.toList());
System.out.println(list.toString());
}
题目要求:一分钟内完成此题,并且只能使用一行代码实现。
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private int id;
private String name;
private int age;
}
import java.util.Arrays;
import java.util.List;
public class Test {
public static void main(String[] args) {
User u1 = new User(1, "a", 21);
User u2 = new User(2, "b", 22);
User u3 = new User(3, "c", 23);
User u4 = new User(4, "d", 24);
User u5 = new User(5, "e", 25);
User u6 = new User(6, "f", 26);
// 将数组变成一个列表集合
List<User> list = Arrays.asList(u1, u2, u3, u4, u5, u6);
// Stream流式计算、lambda表达式、函数式接口 和 链式编程
list.stream()
// 过滤
.filter(user -> {return user.getId()%2==0;})
// 过滤
.filter(user -> {return user.getAge()>21;})
// 转换
.map(user -> {return user.getName().toUpperCase();})
// 排序
.sorted((user1, user2)->{return user2.compareTo(user1);})
// 截断
.limit(2)
// 遍历
.forEach(System.out::println);
}
}