一、Steam說明
Steam與IO無任何關係。
Java 8 中的Steam是對集合 (Collection) 對象功能的增強, 他專注於對集合對象進行各種非常便利,高效的聚合操作(aggregate operation), 或者大批量數據操作 (bulk data operation).
Steam API藉助於同樣新出現的Lambda 表達式, 極大的提高編程效率和程序可讀性. 同時他提供穿行和並行兩種模式進行匯聚操作, 併發模式能夠成分利用多核處理器的優勢, 使用fork/join 並行法師來拆分任務和加速處理過程.
通常編寫並行代碼很難而且容易出錯, 但使用Steam API無需編寫一行多線程的代碼, 就可以很方便地寫出高性能的併發代碼.
Java 8中首次出現的java.util.stream是一個函數式語言+多核時代綜合影響的產物.
二、java7於java8 Steam的使用對比
需要使用到的實體類
@Setter
@Getter
public class Apple {
private Long appleId;
private String appleName;
public Apple(){}
public Apple(Long appleId,String appleName){
this.appleId=appleId;
this.appleName=appleName;
}
}
以下是一個java7對list的操作,包括了篩選、排序、取值等操作。
public static void java7(){
//目標,獲取id大於10的蘋果名稱,並對結果集按照id大小排序
List<Apple> list=getList();
List<Apple> targetList=new ArrayList<>();
for(Apple apple : list){
if(apple.getAppleId()>10){
targetList.add(apple);
}
}
Collections.sort(targetList, new Comparator<Apple>() {
@Override
public int compare(Apple o1, Apple o2) {
return o2.getAppleId().compareTo(o1.getAppleId());
}
});
List<String> nameList=new ArrayList<>();
for(Apple apple : targetList){
nameList.add(apple.getAppleName());
}
XLogUtils.info(jsonToString(nameList));
}
java8對列表進行篩選、排序、取值操作
是不是很清爽?那麼…那麼代價是什麼呢?看完全文你就知道啦。
public static void java8(){
List<Apple> list=getList();
List studentList = list.stream()
.filter(x->x.getAppleId()>10)
.sorted(Comparator.comparing(Apple::getAppleId).reversed())
.map(Apple::getAppleName)
.collect(Collectors.toList());
XLogUtils.info(jsonToString(studentList));
}
三、Steam概述
1、steam的特性
- 不存儲數據
- 不改變數據源
- 延遲執行
2、steam的創建
- 可以通過已存在的數組創建
- 可以通過已存在集合創建
- 可以創建一個空的流
- 可以創建一個無限的流
- 可以創建一個規律的流
3、對Steam的操作
- 一般使用
- 提取流、組合流
- 聚合操作
- Optional類型說明
- 分組與分片
- 收集結果
4、並行流
5、原始類型流
四、Steam使用以及說明
1、Steam的延遲特性
(1)延遲性驗證
public static boolean filter(Apple s) {
System.out.println("begin compare");
return s.getAppleId() > 5;
}
/**
* 驗證延遲性
*/
public static void f2() {
List<Apple> list=getList();
Stream<Apple> stream = list.stream()
.filter(apple -> filter(apple));
System.out.println("split-----------------------------------");
List<Apple> studentList = stream.collect(Collectors.toList());
System.out.println("end-------------------------------------");
}
輸出:
split-----------------------------------
begin compare
begin compare
begin compare
begin compare
begin compare
begin compare
begin compare
begin compare
begin compare
begin compare
end-------------------------------------
由上述可確認,steam確實是具有延遲性。
(2)延遲性事故
/**
* 延遲特性,導致的空指針異常
*/
public static void f4(){
List<Apple> list=getList();
Stream<Apple> appleList= list.stream();
appleList.forEach(s -> {
System.out.println("s->"+s);
if (s.getAppleId() < 4) {
System.out.println("select->"+s);
list.remove(s);
XLogUtils.info(jsonToString(list));
}
});
}
輸出:
select->steam.Apple@71bbf57e
[info]>>>>null
s->steam.Apple@7f13d6e
select->steam.Apple@7f13d6e
[info]>>>>null
s->steam.Apple@51cdd8a
select->steam.Apple@51cdd8a
[info]>>>>null
s->null
Exception in thread “main” java.lang.NullPointerException
at steam.TestSteamClass.lambda$f4ArrayListSpliterator.forEachRemaining(ArrayList.java:1382)
at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:580)
at steam.TestSteamClass.f4(TestSteamClass.java:169)
at steam.TestSteamClass.main(TestSteamClass.java:38)
如上,出現了空指針異常。出現異常的是
if (s.getAppleId() < 4) {
s對象空指針異常。list.remove(s);使對象被remove,但是此處又調用了此對象的方法,導致空指針異常。
(3)延遲性的使用
List<Apple> list=getList();
Stream<Apple> stream = list.stream()
.filter(apple -> filter(apple));
list.add(new Apple(1001L,"New Apple"));
List<Apple> studentList = stream.collect(Collectors.toList());
指令執行的順序爲:
[1]獲取數據源
[2]聲明steam
[3]添加數據到數據源
[4]執行steam業務(過濾),並聚合爲list。
所以,雖然add操作是在聲明steam之後,但是它也被執行過濾。
2、創建steam
(1)通過數組創建流
/**
* 通過數組創建流
*/
@Test
public void testArrayStream(){
//1.通過Arrays.stream
//1.1基本類型
int[] arr = new int[]{1,2,34,5};
IntStream intStream = Arrays.stream(arr);
//1.2引用類型
Student[] studentArr = new Student[]{new Student("s1",29),new Student("s2",27)};
Stream<Student> studentStream = Arrays.stream(studentArr);
//2.通過Stream.of
Stream<Integer> stream1 = Stream.of(1,2,34,5,65);
//注意生成的是int[]的流
Stream<int[]> stream2 = Stream.of(arr,arr);
stream2.forEach(System.out::println);
}
(2)通過集合創建流
@Test
public void testCollectionStream(){
List<String> strs = Arrays.asList("11212","dfd","2323","dfhgf");
//創建普通流
Stream<String> stream = strs.stream();
//創建並行流
Stream<String> stream1 = strs.parallelStream();
}
(3)創建空的流
@Test
public void testEmptyStream(){
//創建一個空的stream
Stream<Integer> stream = Stream.empty();
}
(4)創建無限流
@Test
public void testUnlimitStream(){
//創建無限流,通過limit提取指定大小
Stream.generate(()->"number"+new Random().nextInt()).limit(100).forEach(System.out::println);
Stream.generate(()->new Student("name",10)).limit(20).forEach(System.out::println);
}
(5)創建規律的無限流
@Test
public void testUnlimitStream1(){
Stream.iterate(0,x->x+1).limit(10).forEach(System.out::println);
Stream.iterate(0,x->x).limit(10).forEach(System.out::println);
//Stream.iterate(0,x->x).limit(10).forEach(System.out::println);與如下代碼意思是一樣的
Stream.iterate(0, UnaryOperator.identity()).limit(10).forEach(System.out::println);
}
參考文章:https://www.cnblogs.com/andywithu/p/7404101.html
參考文章:https://www.jianshu.com/p/9101b2ef96d8