函数式编程,Stream使用汇总

  • 各种数据结构转流
  • 高级收集器,返回各种数据类型
  • 流的拼接
  • 排序
  • 分区与分组
  • 归约
  • 其他
  1 package stream;
  2 
  3 import java.util.ArrayList;
  4 import java.util.Arrays;
  5 import java.util.Collection;
  6 import java.util.Comparator;
  7 import java.util.HashMap;
  8 import java.util.HashSet;
  9 import java.util.IdentityHashMap;
 10 import java.util.Iterator;
 11 import java.util.LinkedHashMap;
 12 import java.util.List;
 13 import java.util.Map;
 14 import java.util.Map.Entry;
 15 import java.util.Random;
 16 import java.util.Set;
 17 import java.util.StringJoiner;
 18 import java.util.function.Function;
 19 import java.util.stream.Collectors;
 20 import java.util.stream.IntStream;
 21 import java.util.stream.Stream;
 22 import java.util.stream.StreamSupport;
 23 
 24 public class Test10 {
 25     
 26     static List<Integer> numbers = Arrays.asList(1, 5, 3, 2, 4);
 27     
 28     static List<String> strs = Arrays.asList("b2", "b1", "a2", "c", "b", "a");
 29     
 30     static List<List<String>> strsList = Arrays.asList(strs);
 31     
 32     static Person p1 = new Person(GenderEnum.MALE, 20, "Jack");
 33     static Person p2 = new Person(GenderEnum.FEMALE, 20, "Lily");
 34     static Person p3 = new Person(GenderEnum.MALE, 10, "John");
 35     static Person p4 = new Person(GenderEnum.FEMALE, 10, "Lucy");
 36     static Person p5 = new Person(GenderEnum.MALE, 20, "Eason");
 37 
 38     static List<Person> persons = Arrays.asList(p1, p2, p3, p4, p5);
 39 
 40     static void method1() {
 41         // 常用数据结构转流的方式
 42 
 43         // Collection接口 提供了stream()方法
 44 
 45         // 1. List转流
 46         List<String> list = new ArrayList<>();
 47         Stream<String> streamA = list.stream();
 48 
 49         // ------------------------------------------------------------
 50         
 51         // 2. Set转流
 52         Set<String> set = new HashSet<>();
 53         Stream<String> streamB = set.stream();
 54 
 55         // ------------------------------------------------------------
 56         
 57         // 3. Map转流
 58         Map<String, Integer> map = new HashMap<>();
 59         Stream<Entry<String, Integer>> streamC = map.entrySet().stream();
 60         Stream<Integer> streamD = map.values().stream();
 61 
 62         // ------------------------------------------------------------
 63         
 64         // 4. 数组转流
 65         String[] arr = { "A", "B", "C" };
 66         Arrays.stream(arr);
 67 
 68         // ------------------------------------------------------------
 69         
 70         // 5. Iterable转流
 71         Iterable<String> iterable = new ArrayList<>();
 72         StreamSupport.stream(iterable.spliterator(), false);
 73     }
 74     
 75     static void method2() {
 76         // 流的拼接
 77         
 78         List<String> listA = Arrays.asList("s1", "s2", "s3");
 79         List<String> listB = Arrays.asList("t1", "t2", "t3");
 80 
 81         // Stream.concat()实现多个流拼接
 82         Stream<String> streamA = Stream.concat(listA.stream(), listB.stream());
 83 
 84         // Stream.of()实现拼接
 85         // 多个元素
 86         Stream<String> streamB = Stream.of("A", "B", "C");
 87         // 多个List
 88         Stream<String> streamC = Stream.of(listA, listB).flatMap(Collection::stream);
 89         // 多个Stream
 90         Stream<String> streamD = Stream.of(listA.stream(), listB.stream()).flatMap(Function.identity());
 91 
 92         // flatMap实现子元素拼接
 93         List<Item> items = new ArrayList<>();
 94         Stream<String> streamE = items.stream().flatMap(i -> i.getSubItems().stream());
 95         Stream<String> streamF = items.stream().map(Item::getSubItems).flatMap(Collection::stream);
 96     }
 97 
 98     static void method3() {
 99         // 高级收集器
100     
101         // 1. 字符串拼接
102     
103         List<String> strs = Arrays.asList("s1", "s2", "s3");
104     
105         // 无分隔符
106         String str1 = strs.stream().collect(Collectors.joining());
107         // 单个分隔符
108         String str2 = strs.stream().collect(Collectors.joining(","));
109         // 前后缀及分隔符
110         String str3 = strs.stream().collect(Collectors.joining(",", "[", "]"));
111     
112         // ----------------------------------------------------------------------------------------------------
113     
114         // 返回集合
115     
116         // 2. 返回数组
117     
118         // Object数据(无参默认)
119         Object[] arr1 = strs.stream().toArray();
120         // 特定类型数据
121         String[] arr2 = strs.stream().toArray(String[]::new);
122         // 数组指定长度
123         String ids = "1, 2, 3, 4";
124         String[] arr3 = Arrays.asList(ids.split(",")).stream().map(String::trim).toArray(size -> new String[size]);
125     
126         // ----------------------------------------------------------------------------------------------------
127         
128         // 3. 返回List
129         // 默认List
130         List<String> list1 = strs.stream().filter(str -> str.length() > 5).map(String::toUpperCase).collect(Collectors.toList());
131         // 返回特定类型如ArrayList
132         List<String> list2 = strs.stream().filter(str -> str.length() > 5).map(String::toUpperCase).collect(Collectors.toCollection(ArrayList::new));
133     
134         // ----------------------------------------------------------------------------------------------------
135 
136         // 4. 返回Map
137         
138         // List转Map
139         List<Item> items = Arrays.asList(new Item("0001", "name"), new Item("0002", "name2"));
140         // 成员作为value
141         Map<String, String> map1 = items.stream().collect(Collectors.toMap(Item::getItemId, Item::getName));
142         // 元素作为value
143         Map<String, Item> map2 = items.stream().collect(Collectors.toMap(Item::getItemId, Function.identity()));
144         // value重复取第一个
145         Map<String, Item> map3 = items.stream().collect(Collectors.toMap(Item::getItemId, Function.identity(), (n1, n2) -> n1));
146         // value重复自定义异常,指定返回类型
147         Map<String, Item> map4 = items.stream()
148                 .collect(Collectors.toMap(Item::getItemId, Function.identity(), (a, b) -> {
149                     throw new IllegalStateException("cannot add duplicate key: " + a);
150                 }, IdentityHashMap::new));
151         
152         // Map转Map
153         Map<String, Integer> map = new HashMap<>();
154         Map<String, Integer> map_ = map.entrySet().stream().filter(e -> e.getValue() > 10).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
155     }
156 
157     static void method4() {
158         // 排序 sorted
159         
160         // 数字排序
161     
162         List<Integer> numbers = Arrays.asList(1, 5, 3, 2, 4);
163     
164         // 1. 升序(默认)
165         numbers.stream().sorted();
166         // 1, 2, 3, 4, 5
167     
168         // 2. 降序
169         numbers.stream().sorted(Comparator.reverseOrder());
170         // 5, 4, 3, 2, 1
171     
172         // --------------------------------------------------------------------------------
173     
174         // 字符排序
175     
176         List<String> strs = Arrays.asList("b2", "b1", "a2", "c", "b", "a");
177     
178         // 1. 默认
179         List<String> strSorted1 = strs.stream().sorted().collect(Collectors.toList());
180         // a, a2, b, b1, b2, c
181     
182         // 2. 自定义:先比较长度
183         strs.stream().sorted((s1, s2) -> s1.length() - s2.length());
184         List<String> strSorted2 = strs.stream()
185                 .sorted(Comparator.comparing(String::length).thenComparing(Comparator.naturalOrder()))
186                 .collect(Collectors.toList());
187         // a, b, c, a2, b1, b2
188     
189         // --------------------------------------------------------------------------------
190     
191         // 自定义类型排序
192     
193 
194         // 1. 可实现Comparable<T>接口
195         List<Person> pVal = persons.stream().sorted().collect(Collectors.toList());
196         /*
197          * Person [gender=MALE, age=10, name=John] 
198          * Person [gender=MALE, age=20, name=Eason] 
199          * Person [gender=MALE, age=20, name=Jack] 
200          * Person [gender=FEMALE, age=10, name=Lucy]
201          * Person [gender=FEMALE, age=20, name=Lily]
202          * 
203          */
204         
205         // List可直接排序,传入compareTo方法引用
206         List<Person> personsNew = new ArrayList<>(persons);
207         personsNew.sort(Person::compareTo);
208     
209         // 2. 使用比较器链,排序方式更灵活
210         persons.sort(Comparator.comparing(Person::getAge).thenComparing(Person::getGender).thenComparing(Person::getName));
211          /*
212          * Person [gender=MALE, age=10, name=John]
213          * Person [gender=FEMALE, age=10, name=Lucy]
214          * Person [gender=MALE, age=20, name=Eason]
215          * Person [gender=MALE, age=20, name=Jack]
216          * Person [gender=FEMALE, age=20, name=Lily]
217          * 
218          */
219     }
220 
221     static void method5() {
222         // 分组与分区
223         
224         // 分组
225         Map<GenderEnum, List<Person>> grouped1 = persons.stream().collect(Collectors.groupingBy(Person::getGender));
226         // 子分组,多个分组
227         Map<GenderEnum, Map<Integer, List<Person>>> grouped2 = persons.stream()
228                 .collect(Collectors.groupingBy(Person::getGender, LinkedHashMap::new,
229                         Collectors.groupingBy(Person::getAge, LinkedHashMap::new, Collectors.toList())));
230     
231         // --------------------------------------------------------------------------------
232         
233         // 分区
234         Map<Boolean, List<Person>> partitioned1 = persons.stream().collect(Collectors.partitioningBy(person -> person.getAge() <= 6));
235         // 分区并计数
236         Map<Boolean, Long> partitioned2 = persons.stream().collect(Collectors.partitioningBy(person -> person.getAge() <= 6, Collectors.counting()));
237     }
238     
239     static <T> void method6() {
240         // 归约 reduce
241         
242         // 数字
243         Integer reduced1 = numbers.stream().reduce((x, y) -> x + y).get();
244         // 数字,指定初始值
245         Integer reduced2 = numbers.stream().reduce(0, (x, y) -> x + y);
246         
247         // 字符串拼接
248         String reduced3 = strs.stream().reduce((s1, s2) -> s1 + s2).get();
249         // 字符串拼接,指定前缀
250         String reduced4 = strs.stream().reduce("prefix", (s1, s2) -> s1 + s2);
251 
252         // --------------------------------------------------------------------------------
253 
254         // 数字,求最小值
255         Integer min = numbers.stream().reduce(Math::min).get();
256         // 数字,求最大值
257         Integer max = numbers.stream().reduce(Math::max).get();
258         // 数字,求和
259         Integer sum = numbers.stream().reduce(Integer::sum).get();
260 
261         // --------------------------------------------------------------------------------
262         
263         // 实现流的拼接
264         Stream<String> reduced5 = strsList.stream().map(list -> list.stream()).reduce(Stream::concat).get();
265         
266         Iterable<T>[] inputs = null;
267         Iterator<T> iterator = Stream.of(inputs).map(it -> StreamSupport.stream(it.spliterator(), false)).reduce(Stream::concat).orElseGet(Stream::empty).iterator();
268 
269     }
270     
271     static void method7() {
272         // findFirst 返回第一个符合条件
273         strs.stream().filter(str -> str.length() > 10).findFirst().get();
274         // findAny 返回任意一个符合条件,串行流和findFirst相同,并行流返回最先有值的线程
275         strs.stream().filter(str -> str.length() > 10).findAny().get();
276         // anyMatch 任意符合
277         boolean flag1 = strs.stream().anyMatch(str -> str.length() > 10);
278         // allMatch 全部符合
279         boolean flag2 = strs.stream().allMatch(str -> str.length() > 10);
280         // noneMatch 全不符合
281         boolean flag3 = strs.stream().noneMatch(str -> str.length() > 10);
282         
283         // --------------------------------------------------------------------------------
284         
285         // distinct 去重
286         strs.stream().distinct();
287         // count 计数
288         strs.stream().filter(str -> str.length() > 10).count();
289         // skip 跳过
290         strs.stream().filter(str -> str.length() > 10).skip(3);
291         // limit 限定数量
292         strs.stream().filter(str -> str.length() > 10).limit(3);
293         
294         // --------------------------------------------------------------------------------
295         
296         // 遍历
297         strs.stream().forEach(System.out::println);
298         
299     }
300     
301     static void method8() {
302         // IntStream
303         
304         // 使用IntStream生成50个连续字符
305         
306         IntStream.range(0, 50).mapToObj(s -> "*").collect(Collectors.joining());
307         IntStream.range(0, 50).mapToObj(s -> "*").collect(Collectors.joining(""));
308         IntStream.rangeClosed(1, 50).mapToObj(s -> "*").reduce((s1, s2) -> s1 + s2).get();
309         IntStream.rangeClosed(1, 50).mapToObj(s -> "*").reduce(new StringJoiner("", "[", "]"), StringJoiner::add, StringJoiner::merge);
310         
311         // 生成随机数
312         Random random = new Random();
313         IntStream.generate(random::nextInt);
314         
315         // 生成特定元素
316         IntStream.iterate(1, i -> i * 2);
317     }
318 
319     static class Person implements Comparable<Person> {
320         private GenderEnum gender;
321         private int age;
322         private String name;
323 
324         public Person(GenderEnum gender, int age, String name) {
325             this.gender = gender;
326             this.age = age;
327             this.name = name;
328         }
329 
330         public GenderEnum getGender() {
331             return gender;
332         }
333 
334         public void setGender(GenderEnum gender) {
335             this.gender = gender;
336         }
337 
338         public int getAge() {
339             return age;
340         }
341 
342         public void setAge(int age) {
343             this.age = age;
344         }
345 
346         public String getName() {
347             return name;
348         }
349 
350         public void setName(String name) {
351             this.name = name;
352         }
353 
354         @Override
355         public int compareTo(Person o) {
356             if (this.gender != o.gender) {
357                 return this.gender.compareTo(o.gender);
358             }
359             if (this.age != o.age) {
360                 return this.age - o.age;
361             }
362 
363             return this.name.compareTo(o.name);
364         }
365 
366         @Override
367         public String toString() {
368             return "Person [gender=" + gender + ", age=" + age + ", name=" + name + "]";
369         }
370     }
371 
372     enum GenderEnum {
373         MALE, FEMALE
374     }
375     
376     static class Item {
377         private String itemId;
378         private String name;
379         private String value;
380         private List<String> subItems;
381 
382         public Item(String itemId, String name) {
383             this.itemId = itemId;
384             this.name = name;
385         }
386 
387         public String getItemId() {
388             return itemId;
389         }
390 
391         public void setItemId(String itemId) {
392             this.itemId = itemId;
393         }
394 
395         public String getName() {
396             return name;
397         }
398 
399         public void setName(String name) {
400             this.name = name;
401         }
402 
403         public String getValue() {
404             return value;
405         }
406 
407         public void setValue(String value) {
408             this.value = value;
409         }
410 
411         public List<String> getSubItems() {
412             return subItems;
413         }
414 
415         public void setSubItems(List<String> subItems) {
416             this.subItems = subItems;
417         }
418 
419         @Override
420         public String toString() {
421             return "Item [itemId=" + itemId + ", name=" + name + ", value=" + value + ", subItems=" + subItems + "]";
422         }
423     }
424 
425     public static void main(String[] args) {
426         method5();
427     }
428 }
posted on 2019-07-11 23:39  blouson  阅读(956)  评论(0编辑  收藏  举报