- 說到Stream便容易想到I/O Stream实辑,而實(shí)際上零抬,誰規(guī)定“流”就一定是“IO流”呢?在Java 8中沛膳,得益于Lambda所帶來的函數(shù)式編程
- 引入了一個(gè)全新的Stream概念扁远,用于解決已有集合+數(shù)組既有的弊端俊鱼。
/*
使用Stream流的方式,遍歷集合,對集合中的數(shù)據(jù)進(jìn)行過濾
Stream流是JDK1.8之后出現(xiàn)的
關(guān)注的是做什么,而不是怎么做
*/
public class Demo02Stream {
public static void main(String[] args) {
//創(chuàng)建一個(gè)List集合,存儲姓名
List<String> list = new ArrayList<>();
list.add("張無忌");
list.add("周芷若");
list.add("趙敏");
list.add("張強(qiáng)");
list.add("張三豐");
//對list集合中的元素進(jìn)行過濾,只要以張開頭的元素,存儲到一個(gè)新的集合中
//對listA集合進(jìn)行過濾,只要姓名長度為3的人,存儲到一個(gè)新集合中
//遍歷listB集合
// 獲取流、過濾姓張畅买、過濾長度為3并闲、逐一打印
list.stream()
.filter(name->name.startsWith("張"))
.filter(name->name.length()==3)
.forEach(name-> System.out.println(name));
}
}
- 使用一個(gè)流的時(shí)候,通常包括三個(gè)基本步驟:獲取一個(gè)數(shù)據(jù)源(source)→ 數(shù)據(jù)轉(zhuǎn)換→執(zhí)行操作獲取想要的結(jié)果谷羞,每次轉(zhuǎn)換原有 Stream 對象不改變帝火,返回一個(gè)新的 Stream 對象(可以有多次轉(zhuǎn)換)
獲取流 - java.util.stream.Stream<T> 是Java 8新加入的最常用的流接口。(這并不是一個(gè)函數(shù)式接口湃缎。)
- 獲取一個(gè)流非常簡單犀填,有以下幾種常用的方式:
- 所有的 Collection 集合都可以通過 stream 默認(rèn)方法獲取流;
- Stream 接口的靜態(tài)方法 of 可以獲取數(shù)組對應(yīng)的流嗓违。
/*
java.util.stream.Stream<T>是Java 8新加入的最常用的流接口九巡。(這并不是一個(gè)函數(shù)式接口。)
獲取一個(gè)流非常簡單蹂季,有以下幾種常用的方式:
- 所有的Collection集合都可以通過stream默認(rèn)方法獲取流冕广;
default Stream<E> stream?()
- Stream接口的靜態(tài)方法of可以獲取數(shù)組對應(yīng)的流。
static <T> Stream<T> of?(T... values)
參數(shù)是一個(gè)可變參數(shù),那么我們就可以傳遞一個(gè)數(shù)組
*/
public class Demo01GetStream {
public static void main(String[] args) {
//把集合轉(zhuǎn)換為Stream流
List<String> list = new ArrayList<>();
Stream<String> stream1 = list.stream();
Set<String> set = new HashSet<>();
Stream<String> stream2 = set.stream();
Map<String,String> map = new HashMap<>();
//獲取鍵,存儲到一個(gè)Set集合中
Set<String> keySet = map.keySet();
Stream<String> stream3 = keySet.stream();
//獲取值,存儲到一個(gè)Collection集合中
Collection<String> values = map.values();
Stream<String> stream4 = values.stream();
//獲取鍵值對(鍵與值的映射關(guān)系 entrySet)
Set<Map.Entry<String, String>> entries = map.entrySet();
Stream<Map.Entry<String, String>> stream5 = entries.stream();
//把數(shù)組轉(zhuǎn)換為Stream流
Stream<Integer> stream6 = Stream.of(1, 2, 3, 4, 5);
//可變參數(shù)可以傳遞數(shù)組
Integer[] arr = {1,2,3,4,5};
Stream<Integer> stream7 = Stream.of(arr);
String[] arr2 = {"a","bb","ccc"};
Stream<String> stream8 = Stream.of(arr2);
}
}
forEach
/*
Stream流中的常用方法_forEach
void forEach(Consumer<? super T> action);
該方法接收一個(gè)Consumer接口函數(shù)偿洁,會將每一個(gè)流元素交給該函數(shù)進(jìn)行處理撒汉。
Consumer接口是一個(gè)消費(fèi)型的函數(shù)式接口,可以傳遞Lambda表達(dá)式,消費(fèi)數(shù)據(jù)
簡單記:
forEach方法,用來遍歷流中的數(shù)據(jù)
是一個(gè)終結(jié)方法,遍歷之后就不能繼續(xù)調(diào)用Stream流中的其他方法
*/
public class Demo02Stream_forEach {
public static void main(String[] args) {
//獲取一個(gè)Stream流
Stream<String> stream = Stream.of("張三", "李四", "王五", "趙六", "田七");
//使用Stream流中的方法forEach對Stream流中的數(shù)據(jù)進(jìn)行遍歷
/*stream.forEach((String name)->{
System.out.println(name);
});*/
stream.forEach(name->System.out.println(name));
}
}
filter
/*
Stream流中的常用方法_filter:用于對Stream流中的數(shù)據(jù)進(jìn)行過濾
Stream<T> filter(Predicate<? super T> predicate);
filter方法的參數(shù)Predicate是一個(gè)函數(shù)式接口,所以可以傳遞Lambda表達(dá)式,對數(shù)據(jù)進(jìn)行過濾
Predicate中的抽象方法:
boolean test(T t);
*/
public class Demo03Stream_filter {
public static void main(String[] args) {
//創(chuàng)建一個(gè)Stream流
Stream<String> stream = Stream.of("張三豐", "張翠山", "趙敏", "周芷若", "張無忌");
//對Stream流中的元素進(jìn)行過濾,只要姓張的人
Stream<String> stream2 = stream.filter((String name)->{return name.startsWith("張");});
//遍歷stream2流
stream2.forEach(name-> System.out.println(name));
/*
Stream流屬于管道流,只能被消費(fèi)(使用)一次
第一個(gè)Stream流調(diào)用完畢方法,數(shù)據(jù)就會流轉(zhuǎn)到下一個(gè)Stream上
而這時(shí)第一個(gè)Stream流已經(jīng)使用完畢,就會關(guān)閉了
所以第一個(gè)Stream流就不能再調(diào)用方法了
IllegalStateException: stream has already been operated upon or closed
*/
//遍歷stream流
stream.forEach(name-> System.out.println(name));
}
}
map
/*
Stream流中的常用方法_map:用于類型轉(zhuǎn)換
如果需要將流中的元素映射到另一個(gè)流中,可以使用map方法.
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
該接口需要一個(gè)Function函數(shù)式接口參數(shù)涕滋,可以將當(dāng)前流中的T類型數(shù)據(jù)轉(zhuǎn)換為另一種R類型的流神凑。
Function中的抽象方法:
R apply(T t);
*/
public class Demo04Stream_map {
public static void main(String[] args) {
//獲取一個(gè)String類型的Stream流
Stream<String> stream = Stream.of("1", "2", "3", "4");
//使用map方法,把字符串類型的整數(shù),轉(zhuǎn)換(映射)為Integer類型的整數(shù)
Stream<Integer> stream2 = stream.map((String s)->{
return Integer.parseInt(s);
});
//遍歷Stream2流
stream2.forEach(i-> System.out.println(i));
}
}
count
/*
Stream流中的常用方法_count:用于統(tǒng)計(jì)Stream流中元素的個(gè)數(shù)
long count();
count方法是一個(gè)終結(jié)方法,返回值是一個(gè)long類型的整數(shù)
所以不能再繼續(xù)調(diào)用Stream流中的其他方法了
*/
public class Demo05Stream_count {
public static void main(String[] args) {
//獲取一個(gè)Stream流
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
list.add(6);
list.add(7);
Stream<Integer> stream = list.stream();
long count = stream.count();
System.out.println(count);//7
}
}
limit
/*
Stream流中的常用方法_limit:用于截取流中的元素
limit方法可以對流進(jìn)行截取,只取用前n個(gè)何吝。方法簽名:
Stream<T> limit(long maxSize);
參數(shù)是一個(gè)long型,如果集合當(dāng)前長度大于參數(shù)則進(jìn)行截染槲ā爱榕;否則不進(jìn)行操作
limit方法是一個(gè)延遲方法,只是對流中的元素進(jìn)行截取,返回的是一個(gè)新的流,所以可以繼續(xù)調(diào)用Stream流中的其他方法
*/
public class Demo06Stream_limit {
public static void main(String[] args) {
//獲取一個(gè)Stream流
String[] arr = {"美羊羊","喜洋洋","懶洋洋","灰太狼","紅太狼"};
Stream<String> stream = Stream.of(arr);
//使用limit對Stream流中的元素進(jìn)行截取,只要前3個(gè)元素
Stream<String> stream2 = stream.limit(3);
//遍歷stream2流
stream2.forEach(name-> System.out.println(name));
}
}
skip
/*
Stream流中的常用方法_skip:用于跳過元素
如果希望跳過前幾個(gè)元素,可以使用skip方法獲取一個(gè)截取之后的新流:
Stream<T> skip(long n);
如果流的當(dāng)前長度大于n坡慌,則跳過前n個(gè)黔酥;否則將會得到一個(gè)長度為0的空流。
*/
public class Demo07Stream_skip {
public static void main(String[] args) {
//獲取一個(gè)Stream流
String[] arr = {"美羊羊","喜洋洋","懶洋洋","灰太狼","紅太狼"};
Stream<String> stream = Stream.of(arr);
//使用skip方法跳過前3個(gè)元素
Stream<String> stream2 = stream.skip(3);
//遍歷stream2流
stream2.forEach(name-> System.out.println(name));
}
}
concat
/*
Stream流中的常用方法_concat:用于把流組合到一起
如果有兩個(gè)流,希望合并成為一個(gè)流跪者,那么可以使用Stream接口的靜態(tài)方法concat
static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b)
*/
public class Demo08Stream_concat {
public static void main(String[] args) {
//創(chuàng)建一個(gè)Stream流
Stream<String> stream1 = Stream.of("張三豐", "張翠山", "趙敏", "周芷若", "張無忌");
//獲取一個(gè)Stream流
String[] arr = {"美羊羊","喜洋洋","懶洋洋","灰太狼","紅太狼"};
Stream<String> stream2 = Stream.of(arr);
//把以上兩個(gè)流組合為一個(gè)流
Stream<String> concat = Stream.concat(stream1, stream2);
//遍歷concat流
concat.forEach(name-> System.out.println(name));
}
}
toMap
/**
* 3棵帽、list轉(zhuǎn)為Map
*/
@Test
public void lambatoMap(){
List<User> list = new ArrayList<>();
User user1 = new User("張三",15,"男");
User user2 = new User("李四",22,"男");
User user3 = new User("張三",22,"男");
User user4 = new User("趙六",15,"男");
User user5 = new User("李世民",28,"男");
User user6 = new User("楊貴妃",18,"女");
User user7 = new User("李四",15,"女");
list.add(user1);
list.add(user2);
list.add(user3);
list.add(user4);
list.add(user5);
list.add(user6);
list.add(user7);
//age為key,list轉(zhuǎn)為Map,若key重復(fù)則渣玲,看選擇第一個(gè)對象
Map<Integer, User> collect = list.stream().collect(Collectors.toMap(User::getAge, a -> a,(k1, k2)->k1));
System.out.println(collect);
}
sum
/**
* 5逗概、求和:將集合中的數(shù)據(jù)按照某個(gè)屬性求和
*/
@Test
public void lambamapToInt(){
List<User> list = new ArrayList<>();
User user1 = new User("張三",15,"男");
User user2 = new User("李四",22,"男");
User user3 = new User("張三",22,"男");
User user4 = new User("趙六",15,"男");
User user5 = new User("李世民",28,"男");
User user6 = new User("楊貴妃",18,"女");
User user7 = new User("李四",15,"女");
list.add(user1);
list.add(user2);
list.add(user3);
list.add(user4);
list.add(user5);
list.add(user6);
list.add(user7);
int totalAge = list.stream().mapToInt(User::getAge).sum();
System.out.println("和:" + totalAge);
}
groupingBy
/**
* 2、將List分組:List里面的對象元素忘衍,以某個(gè)屬性來分組
*/
@Test
public void lambagroupBy(){
List<User> list = new ArrayList<>();
User user1 = new User("張三",15,"男");
User user2 = new User("李四",22,"男");
User user3 = new User("張三",22,"男");
User user4 = new User("趙六",15,"男");
User user5 = new User("李世民",28,"男");
User user6 = new User("楊貴妃",18,"女");
User user7 = new User("李四",15,"女");
list.add(user1);
list.add(user2);
list.add(user3);
list.add(user4);
list.add(user5);
list.add(user6);
list.add(user7);
//根據(jù)name來將userList分組
Map<String, List<User>> groupBy = list.stream().collect(Collectors.groupingBy(User::getName));
Map<String, Map<Integer, List<User>>> groupBy = list.stream().collect(Collectors.groupingBy(User::getName,User::getAge));
System.out.println(groupBy);
}
package com.lamba;
public class User {
private String name;
private int age;
private String sex;
public User(String name, int age, String sex) {
super();
this.name = name;
this.age = age;
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String toString() {
return "User [name=" + name + ", age=" + age + ", sex=" + sex + "]";
}
}
更多應(yīng)用請參考:https://blog.csdn.net/chaoer89/article/details/52389458/