Java 8中Stream API
阿新 • • 發佈:2020-09-08
Stream簡介
- Java 8引入了全新的Stream API。這裡的Stream和I/O流不同,它更像具有Iterable的集合類,但行為和集合類又有所不同。
- stream是對集合物件功能的增強,它專注於對集合物件進行各種非常便利、高效的聚合操作,或者大批量資料操作。
- 只要給出需要對其包含的元素執行什麼操作,比如 “過濾掉長度大於 10 的字串”、“獲取每個字串的首字母”等,Stream 會隱式地在內部進行遍歷,做出相應的資料轉換。
為什麼要使用Stream
- 函數語言程式設計帶來的好處尤為明顯。這種程式碼更多地表達了業務邏輯的意圖,而不是它的實現機制。易讀的程式碼也易於維護、更可靠、更不容易出錯。
- 高階
例項資料來源
public class Data { private static List<PersonModel> list = null; static { PersonModel wu = new PersonModel("wu qi",18, "男"); PersonModel zhang = new PersonModel(" zhang san" , 19, "男"); PersonModel wang = new PersonModel( "wang si", 20, "女"); PersonModel zhao = new PersonModel(" zhao wu", 20,“男"); PersonModel chen = new PersonModel("chen liu" ,21, "男"); list = Arrays.asList(wu, zhang, wang, zhao, chen); public static List<PersonModel> getData() { return list; }
Filter
- 遍歷資料並檢查其中的元素時使用。
- filter接受一個函式作為引數,該函式用Lambda表示式表示。
過濾所有的男性 public static void fiterSex(){ List<PersonModel> data = Data . getData(); //old List<PersonModel> temp=new ArrayList<>(); for (PersonModel person:data) { if ("男".equals(person.getSex))){ temp. add(person); } System. out. println(temp); //new List<PersonModel> collect = data .stream() .filter(person ->“男". equals(person. getSex())) .collect(toList()); System. out. println(collect); } /** 過濾所有的男性並且小於20歲 **/ public static void fiterSexAndAge(){ List<PersonModel> data - Data. getData(); //old List<PersonModel> temp=new ArrayList<>(); for (PersonModel person:data) { if ("男".equals(person.getSex() )&&person.getAge()<20){ temp . add(person); } //new 1 List<PersonModel> collect = data .stream() .filter(person -> { if ("男" .equals(person. getSex()8&person. getAge()<28){ return true; } return false; }) .collect(toList()); //new List<PersonModel> collect1 = data . stream() .filter(person -> (“男" .equals(person.getSex()&person. getAge()<20)) .collect(toList()); }
Map
- map生成的是個一對一對映,for的作用
- 比較常用
- 而且很簡單
/**取出所有的使用者名稱字**/
public static void getUserNameList(){
List<PersonMdel> data = Data. getData();
//old
List<String> list=new ArrayList<>();
for (PersonModel pers ion :data) {
list. add(persion. getName());
System. . out .println(list);
//new 1
List<String> collect = data.stream() . map(person -> person .getName()).collect(toList());
System. out . printIn(collect);
//new 2
List<String> collect1 = data.stream().map(PersonModel::getName).collect(toList());
System.out.printIn(collect1);
//new 3
List<string> collect2 = data . stream() .map(person -> {
System. out . printIn(person . getName());
return person. getName();
}).collect(toList());
FlatMap
顧名思義,跟map差不多,更深層次的操作
但還是有區別的
map和flat返回值不同
Map 每個輸入元素,都按照規則轉換成為另外一個元素。
還有一些場景,是一對多對映關係的,這時需要 flatMap。Map一對一
Flatmap一對多
map和flatMap的方法宣告是不一樣的
(1)
Stream map(Function mapper); (2)
Stream flatMap(Function> mapper); (3) map和flatMap的區別:我個人認為,flatMap的可以處理更深層次的資料,入參為多個list,結果可以返回為一個list,而map是一對一的,入參是多個list,結果返回必須是多個list。通俗的說,如果入參都是物件,那麼flatMap可以操作物件裡面的物件,而map只能操作第一層。
public static void flatMapString() {
List<PersonModel> data = Data . getData();
//返回型別不一樣
List<String> collect - data.stream()
.flatMap(person -> Arrays . stream(person. getName().split(" "))).collect(toList());
List<Stream<String>> collect1 = data.stream()
.map(person -> Arrays . stream(person. getName().split(" "))).collect(toList());
//用map實現
List<String> collect2 - data. stream()
.map(person -> person. getName().split(" "))
.flatMap (Arrays: :stream) . collect(toList());
//另- 種方式
List<string> collect3 = data. stream()
.map(person -> person. getName().split(" "))
.flatMap(str -> Arrays.asList(str). stream()).collect(toList());
}
Reduce
- 感覺類似遞迴
- 數字(字串)累加
public static void reduceTest(){
//累加,初始化值是10
Integer reduce = Stream.of(1, 2, 3, 4)
.reduce(10, (count, item) ->{
System . out . println(”count:"+count);
System . out . println(”item:" +item);
return count + item ;
} );
System. out . println(reduce);
Integer reduce1 = Stream.of(1, 2, 3, 4)
.reduce(0, (x, y) -> x + y);
System. out . println(reduce1);
String reduce2 = Stream.of ("1", "2", "3")
.reduce("e", (x, y) -> (x +",”+ y));
System. . out .println(reduce2);
}
Collect
- collect在流中生成列表,map,等常用的資料結構
- toList()
- toSet()
- toMap()
- 自定義
tolist
public static void tolistTest(){
List<PersonModel> data = Data. getData();
List<String> collect = data. stream()
.map(PersonModel: getName)
.collect(Collectors.toList());
}
/*
toSet
*/
public static void toSetTest(){
List<PersonModel> data = Data .getData();
Set<String> collect = data. stream()
. map(PersonModel: getName )
. collect(Collectors . toSet());
}
toMap
public static void toMapTest(){
List<PersonModel> data - Data . getData();
Map<String. Integery collect = data .stream()
.collect(
Collectors. toMap(PersonModel : :getName, PersonModel: getAge)
);
data. stream()
.collect(Collectors. toMap(per->per . getName(), value->{
return value+"1";
}));
}
/*
指定型別
**/
public static void toTreeSetTest(){
List<PersonModel> data = Data . getData();
TreeSet<PersonModel> collect = data.stream()
.collect (Collectors. toCollection(TreeSet: :new));
System. out . printIn(collect);
}
//分組
public static void toGroupTest(){
List<PersonModel> data = Data. getData();
Map<Boolean, ListcPersonModel>> collect = data. stream()
.col lect(Collectors.groupingBy(per ->“男" . equals(per . get<e)x))));
System. out . println(collect);
}
//分隔
public static void toJoiningTest(){
List<PersonModel> data = Data . getData();
String collect = data.stream()
.map(personModel -> personModel . getName())
.collect(Collectors .joining(",", "{", "}"));
System.out.println(collect);
/* *
*自定義
*/
public static void reduce(){
List<String> collect - Stream.of("1", "2", "3").col1ect(
Collectors .reduc ing(new ArrayList<String>(), x -> Arrays.asList(x), (y, z) -> {
y . addAll(z);
return y;
}));
System. out. println(collect);
Optional
- Optional 是為核心類庫新設計的一個數據型別,用來替換 null 值。
- 人們對原有的 null 值有很多抱怨,甚至連發明這一概念的Tony Hoare也是如此,他曾說這是自己的一個“價值連城的錯誤”
- 用處很廣,不光在lambda中,哪都能用
- Optional.of(T),T為非空,否則初始化報錯
- Optional.ofNullable(T),T為任意,可以為空
- isPresent(),相當於 !=null
- ifPresent(T), T可以是一段lambda表示式 ,或者其他程式碼,非空則執行
public static void main(String[] args) {
PersonModel personMode l=new PersonModel();
//物件為空則打出
Optional<object>。= Opt ional . of (personModel);
System. . out .println(o.ispresent()?o.get():"-");
//名稱為空則打出一
optional<String> name = optional . ofNullable(personModel . getName());
System.out .print In(name . isPresent()?name.get():"-");
//如果不為空,則打出xxx
Optional .ofNullable("test" ).ifPresent(na->{
System . out . println(na+" ifPresent );
});
//如果空, 則返回指定字串
System.out. println(Optional.ofNullable(nul1).orElse("-"));
System . out . println(Optional .ofNullable("1" ).orElse("-"));
//如果空, 則返回指定方法, 或者程式碼
System .out . print ln(Optional .ofNullable(nul1) .orElseGet(()->{
return "hahah";
}));
System. . out .println(Opt ional.ofNullable("1" ).orElseGet(()->{
return "hahah";
}));
//如果空,則可以丟擲異常
System.out.println(Optional.ofNullable("1" ) .orElseThrow(()->{
throw new RuntimeException("ss");
})):
objects . requireNonNull(null,"is nul1");
//利用Optional進行多級判斷
EarthModel earthModel1 = new EarthModel();
//old
if (earthModel!=null){
if (earthModel1.getTea()!=nul1){
11...
}
}
/ /new
Opt ional .ofNullable(earthModel1)
.map(EarthModel::getTea)
.map(TeaModel::getType)
.isPresent();
//
Optional<EarthModel> earthModel = Optional.ofNullable(new EarthModel());
Optional<List<PersonModel>> personModels =
earthModel. map( EarthModel: :getPersonModels);
//
Optional<Stream<String>> stringStream = personModels .map(per ->
per stream( ). map(PersonModel:: getName));
/ /判斷物件 中的list
Optional .ofNullable(new EarthMode1())
. map(EarthModel: :getPersonModels)
.map(pers->pers
. stream()
. map(PersonModel: getName)
.collect(toList()))
.ifPresent(per-> System . out .println(per));
List<PersonModel> models=Data . getData();
Opt ional .ofNullable(models)
.map(per -> per
. stream()
. map(PersonModel: :getName)
.collect(toList()))
. ifPresent(per-> System . out . println(per));
}
併發
- stream替換成parallelStream或 parallel
- 輸入流的大小並不是決定並行化是否會帶來速度提升的唯一因素,效能還會受到編寫程式碼的方式和核的數量的影響
- 影響效能的五要素是:資料大小、源資料結構、值是否裝箱、可用的CPU核數量,以及處理每個元素所花的時間