本文介绍了
Stream API
的常见函数:Collect(收集)、Filter(过滤)、Map(转换)、Sorted(排序)、Distinct(去重)、Limit(限制)、Skip(跳过)、Peek(展示)、forEach(遍历)、Count(计数)、Reduce(聚合)、AnyMatch(任意匹配)、AllMatch(全部匹配)、NoneMatch(没有匹配项)等常见的方法,通过将这些方法搭配使用,可以解决大部分开发问题。
文章目录
1、Collect(收集)
collect
方法可以将流中的元素收集到一个集合中。一般与其他方法配合使用。这个方法使用频率很高, collect(Collectors.toList())
是将 stream
流转换成数组。
public class Main {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> list = numbers.stream().filter(n -> n % 2 == 0).collect(Collectors.toList());
System.out.println(list);
}
}
这段代码创建了一个包含整数的列表 numbers,使用流式操作筛选出所有偶数,然后将它们收集到一个新的列表 list 中,并打印输出。
2、Filter(过滤)
filter
方法使用一个结果为 boolean
值的条件对所有元素进行判断,默认结果为 true
的数据可以通过,即结果中只包含判断条件为 true
的数据。
示例:筛选出数组中长度大于 4 的元素。
public class Main {
public static void main(String[] args) {
List<String> names = Arrays.asList("aa", "bbbb", "ccc", "dddddd", "bbbb");
List<String> collect = names.stream().filter(item -> item.length() > 3).collect(Collectors.toList());
// filter 用于过滤,后跟过滤条件,可支持多次过滤
}
}
代码中 names.stream().filter(item -> item.length() > 3)
的结果是一个 Stream<String>
流的 collect
。collect(Collectors.toList())
则将筛选后的结果转换成一个List集合返回。
filter
函数经常搭配一些其他条件或者函数进行使用,例如对数据进行多次过滤并去重:
List<String> collect = names.stream()
.filter(item -> item.length() > 3)
.filter(item -> item.length() < 5)
.distinct()
.collect(Collectors.toList());
3、Map(转换)
map
方法根据设定好的条件对流中的每一个元素进行转换操作,会根据原数据流生成一个新的数据流。常用作对数组对象中数据的计算或修改操作。
public class Main {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> collect = numbers.stream().map(item -> {
item = item * 2;
// 这里需要使用 return,将操作后的结果保存到新的列表中
return item;
}).collect(Collectors.toList()); // 返回一个数组对象
// 使用 toMap 将数字数组 转换成 字节-整数键值对
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 7);
Map<Byte, Integer> collect = numbers.stream().collect(Collectors
.toMap(Integer::byteValue, item -> item * 2, (val1, val2) -> val2));
for (Map.Entry<Byte, Integer> map : collect.entrySet()) {
Byte key = map.getKey();
System.out.println("key = " + key + ", Value = " + map.getValue());
}
}
}
toMap
方法以每个整数的字节值为键,即Integer::byteValue
,- 以该整数乘以 2 为值,即
item -> item * 2
, - 当遇到重复的键时取最后一个值,即
(val1, val2) -> val2
。 - 要注意 Map 的键要具有唯一性。
- 调用
collect(Collectors.toMap(…))
方法转换成Map<Byte, Integer>
。
4、Sorted(排序)
sorted
方法是对流的数据按照规则进行排序。可以接受一个 Comparator
参数,也可以使用自然排序 Ordering.natural()
。默认排序是按 升序
排序,即从小到大 。
public class Main {
public static void main(String[] args) {
int[] num = { 5, 2, 8, 3, 7 };
int[] aa = Arrays.stream(num).sorted().toArray();
System.out.println(Arrays.toString(aa));
// ----- [2, 3, 5, 7, 8]
String[] bb = {"f", "b", "e", "a", "c", "d"};
Object cc = Arrays.stream(bb).sorted().toArray();
System.out.println(Arrays.toString(cc));
// ----- [a, b, c, d, e, f]
}
}
代码使用 Arrays.stream()
方法将其转化为一个 IntStream
流。接下来使用 sorted()
方法对流中的元素进行排序,返回一个新的排序后的 IntStream
流。使用 toArray()
方法将排序后的结果转换为一个新的 int
类型数组,并使用 Arrays.toString()
方法将结果打印到控制台。String
类型数组也是同样操作,排序默认是按照升序进行,即从小到大的顺序。
5、Distinct(去重)
distinct
从流中筛选掉相同的元素,去重操作,返回的数据流结果会按照原顺序排列,被删除的位置会被后面的元素依次补齐。使用 equals()
方法来比较元素是否相同,需要确保 equals()
方法实现。
public class Main {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 2, 1, 4, 6, 4, 5);
List<Integer> collect = numbers.stream().distinct().collect(Collectors.toList());
System.out.println(collect);
// [1, 2, 3, 4, 6, 5]
}
}
6、Limit(限制)
limit
可以将流截取指定的元素数量,例如截取前 3 个元素。这个方法只能从 0 位开始截取,如果需要中间部分的数据,则需要对数组做一定变换操作。例如和下面要讲的 Skip
进行搭配。
public class Main {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> collect = numbers.stream().limit(3).collect(Collectors.toList());
System.out.println(collect);
// [1, 2, 3]
List<Integer> collect1 = numbers.stream().skip(1).limit(3).collect(Collectors.toList());
System.out.println(collect1);
// [2, 3, 4]
}
}
7、Skip(跳过)
跳过数组的部分元素,即生成一个不包含被跳过的数组,常用作对数组的中间部分或后半部分的截取,常与 limit
函数进行搭配。
public class Main {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> collect = numbers.stream().skip(2).collect(Collectors.toList());
System.out.println(collect);
// [3, 4, 5]
List<Integer> collect1 = numbers.stream().skip(1).limit(3).collect(Collectors.toList());
System.out.println(collect1);
// [2, 3, 4]
}
}
8、Peek(展示)
peek
可以用于在Stream流中获取元素同时执行一些操作,如打印、调试、观察等。通常会与其他的方法联合使用。
public class Main {
public static void main(String[] args) {
List<String> names = Arrays.asList("aaa", "bbb", "ccc", "ddd");
List<String> list = names.stream()
.peek(System.out::println)
.filter(name -> name.startsWith("c"))
.peek(name -> System.out.println("value: " + name))
.collect(Collectors.toList());
System.out.println("-----------------------------------------------------------------");
System.out.println(list);
// aaa
// bbb
// ccc
// value: ccc
// ddd
// [ccc]
}
}
9、forEach(遍历)
forEach
方法可将给定的方法应用于流中的每个元素,常用作遍历展示。该方法是一种消费流的方式,不会返回值。
public class Main {
public static void main(String[] args) {
List<String> list = Arrays.asList("aa", "bb", "cc", "dd");
list.stream().forEach(System.out::println);
}
}
10、Count(计数)
count
方法可以返回流中的元素总数。
public class Main {
public static void main(String[] args) {
List<String> names = Arrays.asList("Alex", "Brian", "Charles", "David");
long count = names.stream().count();
System.out.println(count);
}
}
11、Reduce(聚合)
reduce
方法可以将流元素聚合为单个结果。它接受一个 BinaryOperator
参数作为累加器。
public class Main {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> sum = numbers.stream().reduce((a, b) -> a + b);
System.out.println(sum);
// Optional[15]
// 就是将所有数据进行累加
}
}
12、AnyMatch(任意匹配)
anyMatch
方法提供匹配条件,若含有(指整个数组中某一个元素含有),返回 true
。
public class Main {
public static void main(String[] args) {
List<String> names = Arrays.asList("Alex", "Bob", "Cire", "David");
boolean flag = names.stream().anyMatch(name -> name.startsWith("B"));
System.out.println(flag); // true
}
}
使用流式操作检查列表其中是否有任意一个元素以字母 “B” 开头,并将检查结果(布尔值)打印输出。
13、AllMatch(全部匹配)
allMatch
方法提供匹配条件,若含有(指整个数组中所有元素都含有),返回 true
。
public class Main {
public static void main(String[] args) {
List<String> names = Arrays.asList("Alex", "Bob", "Cire", "David");
boolean flag = names.stream().allMatch(name -> name.startsWith("B"));
System.out.println(flag); // false
}
}
14、NoneMatch(没有匹配项)
noneMatch
方法提供匹配条件,若不含有(指整个数组中所有元素都不含有),返回 true
。
public class Main {
public static void main(String[] args) {
List<String> names = Arrays.asList("Alex", "Bob", "Cire", "David");
boolean flag = names.stream().noneMatch(name -> name.startsWith("E"));
System.out.println(flag); // true
}
}