Это первый раз, когда я участвую в Gengwen Challenge.2День, подробности о событии уточняйте:Обновить вызов
Со временем капли воды и камни изнашиваются 😄
Lambda
выражениеStream
основы, если вы не понимаетеLambda
Выражение, рекомендуется сначала выучитьLambda
Выражение, Портал:Java8 — лямбда-выражения
Что такое поток
Stream
Переводы называются «потоками» и являются одной из новых возможностей Java8.Stream
Рассматривайте обрабатываемый элемент как поток, вы можете использоватьStream API
Выполнять промежуточные операции над элементами в потоке, такие как: фильтрация, сортировка, сортировка и т.д.
Функции
- Это не структура данных, она не сохраняет данные, она только манипулирует данными.
- Источник данных не будет изменен, что сохраняет данные после сохранения операции в другом объекте.
- Отложенное выполнение, поток только записывает операцию в процессе промежуточной обработки, и она не будет выполнена сразу, нужно дождаться выполненияЗавершить операциюпри фактическом расчете.
три шага
- 1. Создать поток. Получите поток из источника данных, который может быть коллекцией или массивом.
- 2. Промежуточная операция: цепочка операций, которая может обрабатывать данные в потоке.
- 3. Операция завершения: цепочка операций промежуточной операции будет выполнена только после выполнения операции завершения.После завершения терминальной операции поток нельзя использовать снова, и будет сгенерирован новый результат.
Далее мы представим основное использование трех шагов.
конкретное использование
1. Общие методы создания потоков
- 1.1 Использование
Collection
Коллекция предоставленаstream()
а такжеparallelStream()
метод
public static void main(String[] args) {
// 使用Collection系列集合提供的 stream() 和 parallelStream() 方法
ArrayList<String> list = new ArrayList<>();
//返回一个顺序流
Stream<String> stream = list.stream();
//把顺序流转换成并行流
Stream<String> parallel = list.stream().parallel();
//返回一个并行流
Stream<String> stringStream = list.parallelStream();
}
- 1.2 Использование
Arrays
статический методstream()
Поток массива может быть получен
String[] strs = new String[10];
Stream<String> stream2 = Arrays.stream(strs);
- 1.3 звонок
Stream
статический метод классаof()
Stream<String> aa = Stream.of("aa", "bbb", "c");
- 1.4 Использование статических методов
Stream.iterate()
а такжеStream.generate()
Создавайте неограниченные потоки
//迭代
Stream<Integer> iterate = Stream.iterate(0, (x) -> x + 2);
//0 2 4 6 8
iterate.limit(5).forEach(System.out::println);
//生成
Stream<Double> generate = Stream.generate(() -> Math.random());
//84 28 71
generate.limit(3).forEach(System.out::println);
можно увидеть творениеStream
Есть много способов стримить. Но как бы ты его ни создавал,Stream
Он не сохраняет данные, он просто выполняет вычисления на данных.
2. Промежуточные операции потоков
Промежуточные операции можно разделить на две категории:
- Операция с отслеживанием состояния: вам нужно дождаться предыдущего шага, чтобы завершить операцию и получить все элементы, прежде чем вы сможете работать, например, отсортировать
- Операция без сохранения состояния: на данные этой операции не влияет предыдущая операция, например карта фильтров.
Несколько промежуточных операций могут быть соединены для формирования конвейера, и промежуточные операции не будут выполнять никакой обработки, пока на конвейере не будет запущена операция завершения!
2.1 - Скрининг и нарезка
List<Integer> integers = Arrays.asList(
1,2,3,4,5,6,7,8,9,10,2,5,7,9,17
);
//流的中间操作
@Test
public void test1() {
/**
* 1.筛选与切片
* filter:过滤流中的某些元素
* limit(n):获取n个元素
* skip(n):跳过n元素,若流中元素不足n个,则返回一个空流,配合limit(n)可实现分页
* distinct:通过流中元素的 hashCode() 和 equals() 去除重复元素
*/
// 创建流
Stream<Integer> stream = integers.stream();
// 中间操作
Stream<Integer> integersStream = stream
.filter((t) -> t > 5) //6 7 8 9 10 7 9 17
.distinct() //6 7 8 9 10 17
.skip(2) //8 9 10 17
.limit(3); //8 9 10
integersStream.forEach(System.out::println);
}
2.2 Картирование
1. карта
- 1. Преобразовать каждый элемент в верхний регистр
@Test
public void test2() {
/**
* 1.映 射
* map(Function f):接收一个函数作为参数,该函数会被应用到每个
* 元素上,并将其映射成一个新的元素。
*/
// 将每个元素转换为大写
List<String> list = Arrays.asList("a,a=","b,b=","cc=","d,d=");
List<String> collect = list.stream()
.map(str -> str.toUpperCase()).collect(Collectors.toList());
// str -> str.toUpperCase() 可以简写为 String::toUpperCase
System.out.println(collect);
//结果:[A,A=, B,B=, CC=, D,D=]
}
- 2. Извлечь имя сотрудника
List<Employee> employees = Arrays.asList(
new Employee("张三",18,9999.99),
new Employee("李四",38,5555.55),
new Employee("王五",50,6666.66),
new Employee("赵六",16,3333.33),
new Employee("田七",8,7777.77)
);
//提取员工名称
List<String> collect1 = employees.stream()
//.map(employee -> employee.getName())
//类::实例方法名
.map(Employee::getName)
.collect(Collectors.toList());
System.out.println(collect1);
结果:[张三, 李四, 王五, 赵六, 田七]
2. mapToInt
@Test
public void test3() {
/**
* mapToInt((ToIntFunction f)
* 接收一个函数作为参数,该函数会被应用到每个元素上,
* 产生一个新的 IntStream
*/
//输出每个元素的长度
List<String> list = Arrays.asList("a,a","b,b","cc","d,d");
IntStream intStream = list.stream()
.mapToInt(str -> {
return str.length();
});
intStream.forEach(System.out::println);
}
结果:
3
3
2
3
mapToDouble
,mapToLong
Два других не представлены.
3. плоская карта
@Test
public void test4() {
/**
* flatMap(Function f)
* 接收一个函数作为参数,将流中的每个值都换成另一个流,
* 然后把所有流连接成一个流
*/
// 将每个元素根据,进行分割
List<String> list = Arrays.asList("a,a=","b,b=","cc=","d,d=");
Stream<String> stringStream = list.stream()
.flatMap(str -> {
String[] split = str.split(",");
Stream<String> stream = Arrays.stream(split);
return stream;
});
List<String> collect = stringStream.collect(Collectors.toList());
System.out.println(collect);
}
结果:[a, a=, b, b=, cc=, d, d=]
2.3 Сортировка
1. Сортировка
@Test
public void test5() {
/**
* sorted()
* 产生一个新流,其中按自然顺序排序
*/
List<String> list = Arrays.asList("bb","cc","ee","aa");
list.stream().sorted().forEach(System.out::println);
}
结果:
aa
bb
cc
ee
2. Сортировка (Comparator com)
List<Employee> employees = Arrays.asList(
new Employee("张三",18,9999.99),
new Employee("李四",38,5555.55),
new Employee("王五",50,6666.66),
new Employee("赵六",15,3333.33),
new Employee("田七",18,7777.77)
);
@Test
public void test6() {
/**
* sorted(Comparator com) 产生一个新流,其中按比较器顺序排序
*/
//如果年龄一致,就按照姓名排序,如果不一致,就按照年龄升序排序
employees.stream().sorted((e1,e2)->{
if(e1.getAge().equals(e2.getAge())){
return e1.getName().compareTo(e2.getName());
}else{
return e1.getAge().compareTo(e2.getAge());
}
}).forEach(System.out::println);
}
结果:
name='赵六', age=15, salary=3333.33
name='张三', age=18, salary=9999.99
name='田七', age=18, salary=7777.77
name='李四', age=38, salary=5555.55
name='王五', age=50, salary=6666.66
3. Завершение операции потока
- Терминальные операции производят результаты из конвейера. Результатом может быть любое значение, не являющееся потоком, например.
Например: список, целое число, строка.
- После того, как поток был прерван, его нельзя использовать снова.
1. Подбери и найди
allMatch
Определить, все ли элементы в потоке данных равны aa, и вернуть true, если все равны
List<String> list = Arrays.asList("aa","bb","cc","dd");
@Test
public void test1(){
boolean aa = list.stream()
.allMatch(obj -> obj.equals("aa"));
System.out.println(aa);
}
结果:false
Далее измените все значения List на «aa»
List<String> list = Arrays.asList("aa","aa","aa","aa");
@Test
public void test1(){
boolean aa = list.stream()
.allMatch(obj -> obj.equals("aa"));
System.out.println(aa);
}
结果:true
anyMatch
Определяет, равен ли один из всех элементов в потоке данных aa, и возвращает true, если они равны
List<String> list = Arrays.asList("aa","bb","cc","dd");
@Test
public void test2(){
boolean aa = list.stream()
.anyMatch(obj -> obj.equals("aa"));
System.out.println(aa);
}
结果:true
noneMatch
Определите, все ли элементы в потоке данных равны aa1, и верните true, если ни один из них не соответствует успешно.
List<String> list = Arrays.asList("aa","bb","cc","dd");
@Test
public void test3(){
boolean aa = list.stream()
.noneMatch(obj -> obj.equals("aa1"));
System.out.println(aa);
}
结果:true
findFirst
вернуть первый элемент
List<String> list = Arrays.asList("aa","bb","cc","dd");
@Test
public void test4(){
Optional<String> first = list.stream()
.findFirst();
System.out.println(first.get());
}
结果:aa
findAny
Возвращает любой элемент в текущем потоке
List<String> list = Arrays.asList("bb","aa","cc","dd","d","c","da");
@Test
public void test5(){
Optional<String> first = list.stream()
.findAny();
System.out.println(first.get());
}
结果:bb
Поскольку это последовательный поток, каждый раз возвращается первый элемент. Использование параллельных потоков:
@Test
public void test5(){
Optional<String> first = list.parallelStream()
.findAny();
System.out.println(first.get());
}
结果:d
count
Возвращает общее количество элементов в потоке
List<Integer> numberList = Arrays.asList(1,23,33,4,5,66,21);
@Test
public void test6(){
long count = numberList.stream()
.count();
System.out.println(count);
}
结果:7
max(Comparator c)
Возвращает максимальное значение в потоке
@Test
public void test7(){
Optional<Integer> max = numberList.stream()
.max(Integer::compareTo);
System.out.println(max.get());
}
结果:66
min(Comparator c)
Возвращает наименьшее значение в потоке
@Test
public void test8(){
Optional<Integer> max = numberList.stream()
.min(Integer::compareTo);
System.out.println(max.get());
}
结果:1
forEach(Consumer c)
внутренняя итерация (с использованиемCollection
Интерфейс требует от пользователя итерации, называемой внешней итерацией).
@Test
public void test5() {
/**
* sorted()
* 产生一个新流,其中按自然顺序排序
*/
List<String> list = Arrays.asList("bb","cc","ee","aa");
list.stream().sorted().forEach(System.out::println);
}
4. Устав
-
T reduce(T i, BinaryOperator<T> a)
: Вы можете многократно комбинировать элементы в потоке, чтобы получить значение. вернуть Т
List<Integer> numberList2 = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
@Test
public void test9(){
Integer reduce = numberList2.stream()
.reduce(0, (x1, x2) -> x1 + x2);
System.out.println(reduce);
}
结果:55
Первый параметр — это начальное значение, что, если начальное значение равно 10?
@Test
public void test9(){
Integer reduce = numberList2.stream()
.reduce(10, (x1, x2) -> x1 + x2);
System.out.println(reduce);
}
结果:65
При первом выполнении будетi
(он же 10 ) значение какa
Первый параметр функции, второй параметр - это первый элемент элемента в потоке, при повторном выполнении первый параметр - это результат выполнения первой функции, а второй параметр - это второй параметр. в элементах потока и так далее.
-
Optional<T> reduce(BinaryOperator<T> a)
: вы можете многократно комбинировать элементы в потоке, чтобы получить значение и вернутьOptional<T>
.
@Test
public void test10(){
Optional<Integer> reduce = numberList2.stream()
.reduce(Integer::sum);
System.out.println(reduce.get());
结果:55
}
Процесс аналогичен первому методу, за исключением того, что при его первом выполнении первый параметр — это первый элемент в потоке, а второй параметр — второй элемент элемента в потоке.
5, собирать
Collector
Реализация методов в интерфейсе определяет, как выполнять операцию сбора в потоке (например, сбор в список, набор, карту).
Кроме того,Collectors
Класс предоставляет множество статических методов, с помощью которых можно легко создавать общие экземпляры сборщика.Конкретные методы и экземпляры следующие:
toList
- Получить имя сотрудника и поместить его в коллекцию List
List<Employee> employees = Arrays.asList(
new Employee("张三",18,9999.99),
new Employee("李四",38,5555.55),
new Employee("王五",50,6666.66),
new Employee("赵六",15,3333.33),
new Employee("田七",18,7777.77)
);
@Test
public void test14(){
List<String> collect = employees.stream()
.map(Employee::getName)
.collect(Collectors.toList());
collect.forEach(System.out::println);
}
结果:
张三
李四
王五
赵六
田七
toCollection
- Получите имя сотрудника и введите его
HashSet
в коллекции
@Test
public void test15(){
HashSet<String> hs = employees.stream()
.map(Employee::getName)
.collect(Collectors.toCollection(HashSet::new));
hs.forEach(System.out::println);
}
подсчет, суммированиеDouble, усреднениеDouble, maxBy
Соответственно: количество, сумма, среднее, наибольшее значение
@Test
public void test16(){
//元素的个数
Long l = employees.stream()
.map(Employee::getName)
.collect(Collectors.counting());
System.out.println("个数" + l);
//求和
Double sum = employees.stream()
.collect(Collectors.summingDouble(Employee::getAge));
System.out.println("求和" + sum);
//平均值
Double avg = employees.stream()
.collect(Collectors.averagingDouble(Employee::getAge));
System.out.println("平均值" + avg);
//获得年龄最大的员工信息
Optional<Employee> collect = employees.stream()
.collect(Collectors.maxBy((e1, e2) -> Integer.compare(e1.getAge(), e2.getAge())));
System.out.println("获得年龄最大的员工信息" + collect.get());
}
结果:
个数5
求和139.0
平均值27.8
获得年龄最大的员工信息name='王五', age=50, salary=6666.66
summarizingInt
поток сбораInteger
Статистическая стоимость имущества. например средний
@Test
public void test19(){
IntSummaryStatistics collect = employees.stream()
.collect(Collectors.summarizingInt(Employee::getAge));
System.out.println("个数" + collect.getCount());
System.out.println("求和" + collect.getSum());
System.out.println("最大值" + collect.getMax());
System.out.println("平均值" + collect.getAverage());
System.out.println("最小值" + collect.getMin());
}
结果:
个数5
求和139
最大值50
平均值27.8
最小值15
groupingBy
Разделить поток на несколько карт на основе значения
//根据年龄进行分组
@Test
public void test17(){
Map<Integer, List<Employee>> collect = employees.stream()
.collect(Collectors.groupingBy(Employee::getAge));
for(Map.Entry<Integer,List<Employee>> map : collect.entrySet()){
Integer key = map.getKey();
List<Employee> value = map.getValue();
for (Employee employee : value) {
System.out.println("key=" +key + ",value = "+employee);
}
}
}
结果:
key=50,value = name='王五', age=50, salary=6666.66
key=18,value = name='张三', age=18, salary=9999.99
key=18,value = name='田七', age=18, salary=7777.77
key=38,value = name='李四', age=38, salary=5555.55
key=15,value = name='赵六', age=15, salary=3333.33
- partitioningBy: разделить поток на две Карты по условию,
true
илиfalse
, например: больше ли зарплата 7000
@Test
public void test18(){
Map<Boolean, List<Employee>> collect = employees.stream()
.collect(Collectors.partitioningBy(e -> e.getSalary() > 7000));
for(Map.Entry<Boolean,List<Employee>> map : collect.entrySet()){
Boolean key = map.getKey();
List<Employee> value = map.getValue();
for (Employee employee : value) {
System.out.println("key=" +key + ",value = "+employee);
}
}
}
结果:
key=false,value = name='李四', age=38, salary=5555.55
key=false,value = name='王五', age=50, salary=6666.66
key=false,value = name='赵六', age=15, salary=3333.33
key=true,value = name='张三', age=18, salary=9999.99
key=true,value = name='田七', age=18, salary=7777.77
joining
объединить каждую строку в потоке
@Test
public void test20(){
String collect = employees.stream()
.map(Employee::getName)
.collect(Collectors.joining(",","这些人:","他们好棒"));
System.out.println("str:" + collect);
}
结果:
str:这些人:张三,李四,王五,赵六,田七他们好棒
- Если у вас есть какие-либо вопросы по этой статье или есть ошибки в этой статье, пожалуйста, оставьте комментарий. Если вы считаете, что эта статья была вам полезна, ставьте лайк и подписывайтесь на нее.