1. Stream流
1.1 體驗Stream流
代碼示例:
//需求:按照下面的要求完成集合的創建和遍歷
public class StreamDemo {
public static void main(String[] args) {
// 1:創建一個集合,存儲多個字符串元素
ArrayList<String> list = new ArrayList<String>();
list.add("林青霞");
list.add("張曼玉");
list.add("王祖賢");
list.add("柳巖");
list.add("張敏");
list.add("張無忌");
// 2:把集合中所有以"張“開頭的元素存儲到一個新的集合
ArrayList<String> zhangList = new ArrayList<String>();
// boolean startsWith(String prefix); 測試此字符串是否以指定的前綴開頭。
for (String s : list) {
if (s.startsWith("張")) {
zhangList.add(s);
}
}
// System.out.println(zhangList);
// 3:把"張"開頭的集合中的長度爲3的元素存儲到一個新的集合
ArrayList<String> threeList = new ArrayList<String>();
for (String s : zhangList) {
if (s.length() == 3) {
threeList.add(s);
}
}
// System.out.println(threeList);
// 4:遍歷上一步得到的集合
for (String s : threeList) {
System.out.println(s);
}
System.out.println("---------------");
// Stream流來改進
// list.stream().filter(s -> s.startsWith("張")).filter(s -> s.length() == 3).forEach(s -> System.out.println(s));
list.stream().filter(s -> s.startsWith("張")).filter(s -> s.length() == 3).forEach(System.out::println);
}
}
運行結果:
1.2 Stream流的生成方式
//Stream流的常見生成方式
public class StreamDemo01 {
public static void main(String[] args) {
// 1:Collection體系的集合可以使用默認方法stream ()生成流
// default Stream<E> stream ()
List<String> list = new ArrayList<String>();
Stream<String> listStream = list.stream();
Set<String> set = new HashSet<String>();
Stream<String> setStream = set.stream();
// 2:Map體系的集合間接的生成流
Map<String, Integer> map = new HashMap<String, Integer>();
// 使用key值間接生成Stream流
Stream<String> keyStream = map.keySet().stream();
// 使用value值間接生成Stream流
Stream<Integer> valueStream = map.values().stream();
// 使用鍵值對間接生成Stream流
Stream<Entry<String, Integer>> entryStream = map.entrySet().stream();
// 3:數組可以通過Stream接口的靜態方法of (T... values)生成流
String[] strArray = { "hello", "world", "java" };
Stream<String> strArrayStream = Stream.of(strArray);
// 也可以直接使用參數生成Stream流
Stream<String> strArrayStream2 = Stream.of("hello", "world", "java");
// int類型也可以
Stream<Integer> streamStream3 = Stream.of(10, 20, 30);
}
}
1.3 Stream流的常見中間操作方法
1.3.1 filter
filter(Predicate predicate):方法使用Predicate接口(Lambda表達式)過濾
代碼示例:
public class StreamDemo02 {
public static void main(String[] args) {
// 創建一個集合存儲對個字符串
ArrayList<String> list = new ArrayList<String>();
list.add("林青霞");
list.add("張曼玉");
list.add("王祖賢");
list.add("柳巖");
list.add("張敏");
list.add("張無忌");
// 需求1:把list集合中以張開頭的元素在控制檯輸出
// list.stream().filter((String s) -> {
// return s.startsWith("張");
// }).forEach(System.out::println);
//使用簡化的
list.stream().filter(s -> s.startsWith("張")).forEach(System.out::println);
System.out.println("---------------");
// 需求2:把list集合中長度爲3的元素在控制檯輸出
list.stream().filter(s -> s.length() == 3).forEach(System.out::println);
System.out.println("---------------");
// 需求3:把list集合中以張開頭的,長度爲3的元素在控制檯輸出
list.stream().filter(s -> s.startsWith("張")).filter(s -> s.length() == 3).forEach(System.out::println);
}
}
運行結果:
1.3.2 limit && skip
limit(long maxSize):使用該方法可以截取maxSize個數據
skip(long n):使用該方法可以跳過n個數據
代碼示例:
public class StreamDemo03 {
public static void main(String[] args) {
// 創建一個集合存儲對個字符串
ArrayList<String> list = new ArrayList<String>();
list.add("林青霞");
list.add("張曼玉");
list.add("王祖賢");
list.add("柳巖");
list.add("張敏");
list.add("張無忌");
// 需求1:取前3個數據在控制檯輸出
list.stream().limit(3).forEach(System.out::println);
System.out.println("--------------------------");
// 需求2:跳過3個元素,把剩下的元素在控制檯輸出
list.stream().skip(3).forEach(System.out::println);
System.out.println("--------------------------");
// 需求3:跳過2個元素,把剩下的元素中前2個在控制檯輸出
list.stream().skip(2).limit(2).forEach(System.out::println);
}
}
運行結果:
1.3.3 concat && distinct
concat(Stream a,Stream b) :將a和b兩個流合併
distinct():返回時將重複的元素去掉
代碼示例:
public class StreamDemo04 {
public static void main(String[] args) {
// 創建一個集合存儲對個字符串
ArrayList<String> list = new ArrayList<String>();
list.add("林青霞");
list.add("張曼玉");
list.add("王祖賢");
list.add("柳巖");
list.add("張敏");
list.add("張無忌");
// 需求1:取前4個數據組成一個流
Stream<String> s1 = list.stream().limit(4);
// 需求2:跳過2個數據組成一個流
Stream<String> s2 = list.stream().skip(2);
// 需求3:合併需求1和需求2得到的流,並把結果在控制檯輸出
// Stream.concat(s1, s2).forEach(System.out::println);
// 需求4:合併需求1和需求2得到的流,並把結果在控制檯輸出,要求字符串元素不能重複
Stream.concat(s1, s2).distinct().forEach(System.out::println);
}
}
運行結果:
1.3.4 sorted() && sorted(Comparator comparator)
sorted():將結果安裝自然規則排序
sorted(Comparator comparator):排序規則可以根據,Lambda表達式Comparator,自己定義
代碼示例:
public class StreamDemo05 {
public static void main(String[] args) {
// 創建一個集合存儲對個字符串
ArrayList<String> list = new ArrayList<String>();
list.add("linqingxia");
list.add("zhangmanyu");
list.add("wangzuxian");
list.add("liuyan");
list.add("zhangmin");
list.add("zhangwuji");
// 需求1:按照字母順序把數據在控制檯輸出
list.stream().sorted().forEach(System.out::println);
System.out.println("--------------------");
// 需求2:按照字符串長度把數據在控制檯輸出
list.stream().sorted((s1, s2) -> {
int num = s1.length() - s2.length();
int num2 = num == 0 ? s1.compareTo(s2) : num;
return num2;
}).forEach(System.out::println);
}
}
運行結果:
1.3.5 map && mapToInt
< R >Stream< R > map (Function mapper):該方法根據,Lambda表達式Function接口,使用
IntStream mapToInt (ToIntFunction mapper):該方法和map 是一樣的,只不過該方法返回的是一個IntStream 類型。
代碼示例:
public class StreamDemo06 {
public static void main(String[] args) {
// 創建一個集合存儲對個字符串
ArrayList<String> list = new ArrayList<String>();
list.add("10");
list.add("20");
list.add("30");
list.add("40");
list.add("50");
// 需求:將集合中的字符串數據轉換爲整數之後在控制檯輸出
// <R>Stream<R> map (Function mapper): 返回由給定函數應用於此流的元素的結果組成的流
// list.stream().map(s -> Integer.parseInt(s)).forEach(System.out::println);
list.stream().map(Integer::parseInt).forEach(System.out::println);
System.out.println("----------------");
// 使用IntStream mapToInt (ToIntFunction mapper):
list.stream().mapToInt(Integer::parseInt).forEach(System.out::println);
System.out.println("----------------");
// int sum () 返回此流中元素的總和
// 該方法是是IntStream類獨有的方法
int result = list.stream().mapToInt(Integer::parseInt).sum();
System.out.println(result);
}
}
運行結果:
1.4 Stream流的常見終結操作方法
代碼示例:
public class StreamDemo07 {
public static void main(String[] args) {
// 創建一個集合存儲對個字符串
ArrayList<String> list = new ArrayList<String>();
list.add("林青霞");
list.add("張曼玉");
list.add("王祖賢");
list.add("柳巖");
list.add("張敏");
list.add("張無忌");
// 需求1:把集合中的元素在控制檯輸出
list.stream().forEach(System.out::println);
// 需求2:統計集合中有幾個以張開頭的元素,並把統計結果在控制檯輸出
long count = list.stream().filter((s) -> s.startsWith("張")).count();
System.out.println(count);
}
}
運行結果:
1.5 Stream流的練習
代碼示例:
//現在有兩個Arraylist集合,分別存儲6名男演員名稱和6名女演員名稱,要求完成如下的操作
public class StreamTest {
public static void main(String[] args) {
// 創建集合
ArrayList<String> manList = new ArrayList<String>();
manList.add("周潤發");
manList.add("成龍");
manList.add("劉德華");
manList.add("吳京");
manList.add("周星馳");
manList.add("李連杰");
ArrayList<String> womanList = new ArrayList<String>();
womanList.add("林心如");
womanList.add("張曼玉");
womanList.add("林青震");
womanList.add("柳巖");
womanList.add("林志玲");
womanList.add("王祖賢");
// 1:男演員只要名字爲3個字的前三人
Stream<String> manStream = manList.stream().filter(s -> s.length() == 3).limit(3);
// 2:女演員只要姓林的,並且不要第一個
Stream<String> womanStream = womanList.stream().filter(s -> s.startsWith("林")).skip(1);
// 3:把過濾後的男演員姓名和女演員姓名合併到一起
Stream<String> stream = Stream.concat(manStream, womanStream);
// 4:把上一步操作後的元素作爲構造方法的參數創建演員對象,遍歷數據
// 演員類Actor已經提供,裏面有一個成員變量, 一個帶參構造方法,以及成員變量對應的get/set方法
//map 方法用於映射每個元素到對應的結果
stream.map(Actor::new).forEach(p -> System.out.println(p.getName()));
System.out.println("--------------------");
// 簡化步驟
Stream.concat(manList.stream().filter(s -> s.length() == 3).limit(3),
womanList.stream().filter(s -> s.startsWith("林")).skip(1)).map(Actor::new)
.forEach(p -> System.out.println(p.getName()));
}
}
運行結果:
1.6 Stream流的收集操作(將數據收集到集合中)
代碼示例:
public class CollertDemo {
public static void main(String[] args) {
// 創建List集合
ArrayList<String> list = new ArrayList<String>();
list.add("林青霞");
list.add("張曼玉");
list.add("王祖賢");
list.add("柳巖");
// 需求1:得到名字爲3個字的流
Stream<String> listStream = list.stream().filter(s -> s.length() == 3);
// 需求2:把使用Stream流操作完畢的數據收集到List集合中並遍歷
List<String> listCollect = listStream.collect(Collectors.toList());
for (String s : listCollect) {
System.out.println(s);
}
// 創建Set集合
Set<Integer> set = new HashSet<Integer>();
set.add(10);
set.add(20);
set.add(30);
set.add(33);
set.add(35);
System.out.println("-----------------");
// 需求3:得到年齡大於25的流
Stream<Integer> setStream = set.stream().filter(i -> i > 25);
// 需求4:把使用Stream流操作完畢的數據收集到Set集合中並遍歷
Set<Integer> setCollect = setStream.collect(Collectors.toSet());
for (Integer i : setCollect) {
System.out.println(i);
}
System.out.println("-----------------");
// 定義一個字符串數組,每一個字符串數據由姓名數據和年齡數據組合而成
String[] strArray = { "林青霞,30", "張曼玉,35", "王祖賢,33", "柳巖,25" };
// 需求5:得到字符串中年齡數據大於28的流
Stream<String> arrayStream = Stream.of(strArray).filter(s -> Integer.parseInt(s.split(",")[1]) > 28);
// 需求6:把使用Stream流操作完畢的數據收集到Map集合中並遍歷,字符串中的姓名作鍵,年齡作值
Map<String, Integer> mapStream = arrayStream
.collect(Collectors.toMap((key -> key.split(",")[0]), value -> Integer.parseInt(value.split(",")[1])));
// 遍歷mapStream
Set<String> keySet = mapStream.keySet();
for (String key : keySet) {
Integer value = mapStream.get(key);
System.out.println(key + "." + value);
}
}
}
運行結果: