最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

java8新特性之stream的collect實(shí)戰(zhàn)教程

 更新時(shí)間:2020年08月17日 11:52:02   作者:光哥_帥  
這篇文章主要介紹了java8新特性之stream的collect實(shí)戰(zhàn)教程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧

1、list轉(zhuǎn)換成list

不帶return方式

List<Long> ids=wrongTmpList.stream().map(c->c.getId()).collect(Collectors.toList());

帶return方式

// spu集合轉(zhuǎn)化成spubo集合//java8的新特性
  List<SpuBo> spuBos=spuList.stream().map(spu -> {
   SpuBo spuBo = new SpuBo();
   BeanUtils.copyProperties(spu, spuBo);
   //查詢(xún)品牌名稱(chēng)
   Brand brand = this.brandMapper.selectByPrimaryKey(spu.getBrandId());
   spuBo.setBname(brand.getName());
   //查詢(xún)類(lèi)別名稱(chēng)
   List<String> names = this.categoryService.queryNamesByIds(Arrays.asList(spu.getCid1(), spu.getCid2(), spu.getCid3()));
   spuBo.setCname(StringUtils.join(names, "-"));
   return spuBo;
  }).collect(Collectors.toList());

2、list轉(zhuǎn)map

Map<Long, Active> activeMap = actives.stream().collect(Collectors.toMap(Active::getId, s->s));

3、分組統(tǒng)計(jì)計(jì)算

list轉(zhuǎn)map(根據(jù)某個(gè)屬性進(jìn)行分組)

Map<Long, List<TrainPlan>> trainMaps = trainPlans.stream().collect(

Collectors.groupingBy(TrainPlan::getModuleId));

list轉(zhuǎn)map(統(tǒng)計(jì)計(jì)算)

 List<StatDepartment> statDepartments = projectModuleBSDao.statProModByDepartment(params);

 Map<Long, Integer> projectNumByDep = statDepartments.stream()
    .collect(Collectors.groupingBy(StatDepartment::getDepartmentId, Collectors.summingInt(StatDepartment::getProjectNum)));

補(bǔ)充知識(shí):Java8新特性學(xué)習(xí)-函數(shù)式編程(Stream/Function/Optional/Consumer)

Java8新引入函數(shù)式編程方式,大大的提高了編碼效率。本文將對(duì)涉及的對(duì)象等進(jìn)行統(tǒng)一的學(xué)習(xí)及記錄。

首先需要清楚一個(gè)概念:函數(shù)式接口;它指的是有且只有一個(gè)未實(shí)現(xiàn)的方法的接口,一般通過(guò)FunctionalInterface這個(gè)注解來(lái)表明某個(gè)接口是一個(gè)函數(shù)式接口。函數(shù)式接口是Java支持函數(shù)式編程的基礎(chǔ)。

1 Java8函數(shù)式編程語(yǔ)法入門(mén)

Java8中函數(shù)式編程語(yǔ)法能夠精簡(jiǎn)代碼。

使用Consumer作為示例,它是一個(gè)函數(shù)式接口,包含一個(gè)抽象方法accept,這個(gè)方法只有輸入而無(wú)輸出。

現(xiàn)在我們要定義一個(gè)Consumer對(duì)象,傳統(tǒng)的方式是這樣定義的:

Consumer c = new Consumer() {
 @Override
 public void accept(Object o) {
  System.out.println(o);
 }
};

而在Java8中,針對(duì)函數(shù)式編程接口,可以這樣定義:

Consumer c = (o) -> {
 System.out.println(o);
}; 

上面已說(shuō)明,函數(shù)式編程接口都只有一個(gè)抽象方法,因此在采用這種寫(xiě)法時(shí),編譯器會(huì)將這段函數(shù)編譯后當(dāng)作該抽象方法的實(shí)現(xiàn)。

如果接口有多個(gè)抽象方法,編譯器就不知道這段函數(shù)應(yīng)該是實(shí)現(xiàn)哪個(gè)方法的了。

因此,=后面的函數(shù)體我們就可以看成是accept函數(shù)的實(shí)現(xiàn)。

輸入:->前面的部分,即被()包圍的部分。此處只有一個(gè)輸入?yún)?shù),實(shí)際上輸入是可以有多個(gè)的,如兩個(gè)參數(shù)時(shí)寫(xiě)法:(a, b);當(dāng)然也可以沒(méi)有輸入,此時(shí)直接就可以是()。

函數(shù)體:->后面的部分,即被{}包圍的部分;可以是一段代碼。

輸出:函數(shù)式編程可以沒(méi)有返回值,也可以有返回值。如果有返回值時(shí),需要代碼段的最后一句通過(guò)return的方式返回對(duì)應(yīng)的值。

當(dāng)函數(shù)體中只有一個(gè)語(yǔ)句時(shí),可以去掉{}進(jìn)一步簡(jiǎn)化:

Consumer c = (o) -> System.out.println(o);

然而這還不是最簡(jiǎn)的,由于此處只是進(jìn)行打印,調(diào)用了System.out中的println靜態(tài)方法對(duì)輸入?yún)?shù)直接進(jìn)行打印,因此可以簡(jiǎn)化成以下寫(xiě)法:

Consumer c = System.out::println;

它表示的意思就是針對(duì)輸入的參數(shù)將其調(diào)用System.out中的靜態(tài)方法println進(jìn)行打印。

到這一步就可以感受到函數(shù)式編程的強(qiáng)大能力。

通過(guò)最后一段代碼,我們可以簡(jiǎn)單的理解函數(shù)式編程,Consumer接口直接就可以當(dāng)成一個(gè)函數(shù)了,這個(gè)函數(shù)接收一個(gè)輸入?yún)?shù),然后針對(duì)這個(gè)輸入進(jìn)行處理;當(dāng)然其本質(zhì)上仍舊是一個(gè)對(duì)象,但我們已經(jīng)省去了諸如老方式中的對(duì)象定義過(guò)程,直接使用一段代碼來(lái)給函數(shù)式接口對(duì)象賦值。

而且最為關(guān)鍵的是,這個(gè)函數(shù)式對(duì)象因?yàn)楸举|(zhì)上仍舊是一個(gè)對(duì)象,因此可以做為其它方法的參數(shù)或者返回值,可以與原有的代碼實(shí)現(xiàn)無(wú)縫集成!

下面對(duì)Java中的幾個(gè)預(yù)先定義的函數(shù)式接口及其經(jīng)常使用的類(lèi)進(jìn)行分析學(xué)習(xí)。

2 Java函數(shù)式接口

2.1 Consumer

Consumer是一個(gè)函數(shù)式編程接口; 顧名思義,Consumer的意思就是消費(fèi),即針對(duì)某個(gè)東西我們來(lái)使用它,因此它包含有一個(gè)有輸入而無(wú)輸出的accept接口方法;

除accept方法,它還包含有andThen這個(gè)方法;

其定義如下:

default Consumer<T> andThen(Consumer<? super T> after) {
 Objects.requireNonNull(after);
 return (T t) -> { accept(t); after.accept(t); };
}

可見(jiàn)這個(gè)方法就是指定在調(diào)用當(dāng)前Consumer后是否還要調(diào)用其它的Consumer;

使用示例:

public static void consumerTest() {
 Consumer f = System.out::println;
 Consumer f2 = n -> System.out.println(n + "-F2");

 //執(zhí)行完F后再執(zhí)行F2的Accept方法
 f.andThen(f2).accept("test");

 //連續(xù)執(zhí)行F的Accept方法
 f.andThen(f).andThen(f).andThen(f).accept("test1");
}

2.2 Function

Function也是一個(gè)函數(shù)式編程接口;它代表的含義是“函數(shù)”,而函數(shù)經(jīng)常是有輸入輸出的,因此它含有一個(gè)apply方法,包含一個(gè)輸入與一個(gè)輸出;

除apply方法外,它還有compose與andThen及indentity三個(gè)方法,其使用見(jiàn)下述示例;

/**
 * Function測(cè)試
 */
public static void functionTest() {
 Function<Integer, Integer> f = s -> s++;
 Function<Integer, Integer> g = s -> s * 2;

 /**
  * 下面表示在執(zhí)行F時(shí),先執(zhí)行G,并且執(zhí)行F時(shí)使用G的輸出當(dāng)作輸入。
  * 相當(dāng)于以下代碼:
  * Integer a = g.apply(1);
  * System.out.println(f.apply(a));
  */
 System.out.println(f.compose(g).apply(1));

 /**
  * 表示執(zhí)行F的Apply后使用其返回的值當(dāng)作輸入再執(zhí)行G的Apply;
  * 相當(dāng)于以下代碼
  * Integer a = f.apply(1);
  * System.out.println(g.apply(a));
  */
 System.out.println(f.andThen(g).apply(1));

 /**
  * identity方法會(huì)返回一個(gè)不進(jìn)行任何處理的Function,即輸出與輸入值相等; 
  */
 System.out.println(Function.identity().apply("a"));
}

2.3 Predicate

Predicate為函數(shù)式接口,predicate的中文意思是“斷定”,即判斷的意思,判斷某個(gè)東西是否滿(mǎn)足某種條件; 因此它包含test方法,根據(jù)輸入值來(lái)做邏輯判斷,其結(jié)果為T(mén)rue或者False。

它的使用方法示例如下:

/**
 * Predicate測(cè)試
 */
private static void predicateTest() {
 Predicate<String> p = o -> o.equals("test");
 Predicate<String> g = o -> o.startsWith("t");

 /**
  * negate: 用于對(duì)原來(lái)的Predicate做取反處理;
  * 如當(dāng)調(diào)用p.test("test")為T(mén)rue時(shí),調(diào)用p.negate().test("test")就會(huì)是False;
  */
 Assert.assertFalse(p.negate().test("test"));

 /**
  * and: 針對(duì)同一輸入值,多個(gè)Predicate均返回True時(shí)返回True,否則返回False;
  */
 Assert.assertTrue(p.and(g).test("test"));

 /**
  * or: 針對(duì)同一輸入值,多個(gè)Predicate只要有一個(gè)返回True則返回True,否則返回False
  */
 Assert.assertTrue(p.or(g).test("ta"));
}

3 函數(shù)式編程接口的使用

通過(guò)Stream以及Optional兩個(gè)類(lèi),可以進(jìn)一步利用函數(shù)式接口來(lái)簡(jiǎn)化代碼。

3.1 Stream

Stream可以對(duì)多個(gè)元素進(jìn)行一系列的操作,也可以支持對(duì)某些操作進(jìn)行并發(fā)處理。

3.1.1 Stream對(duì)象的創(chuàng)建

Stream對(duì)象的創(chuàng)建途徑有以下幾種

a. 創(chuàng)建空的Stream對(duì)象

Stream stream = Stream.empty();

b. 通過(guò)集合類(lèi)中的stream或者parallelStream方法創(chuàng)建;

List<String> list = Arrays.asList("a", "b", "c", "d");
Stream listStream = list.stream();     //獲取串行的Stream對(duì)象
Stream parallelListStream = list.parallelStream(); //獲取并行的Stream對(duì)象 

c. 通過(guò)Stream中的of方法創(chuàng)建:

Stream s = Stream.of("test");

Stream s1 = Stream.of("a", "b", "c", "d");

d. 通過(guò)Stream中的iterate方法創(chuàng)建:

iterate方法有兩個(gè)不同參數(shù)的方法:

public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f);

public static<T> Stream<T> iterate(T seed, Predicate<? super T> hasNext, UnaryOperator<T> next)

其中第一個(gè)方法將會(huì)返回一個(gè)無(wú)限有序值的Stream對(duì)象:它的第一個(gè)元素是seed,第二個(gè)元素是f.apply(seed); 第N個(gè)元素是f.apply(n-1個(gè)元素的值);生成無(wú)限值的方法實(shí)際上與Stream的中間方法類(lèi)似,在遇到中止方法前一般是不真正的執(zhí)行的。因此無(wú)限值的這個(gè)方法一般與limit等方法一起使用,來(lái)獲取前多少個(gè)元素。

當(dāng)然獲取前多少個(gè)元素也可以使用第二個(gè)方法。

第二個(gè)方法與第一個(gè)方法生成元素的方式類(lèi)似,不同的是它返回的是一個(gè)有限值的Stream;中止條件是由hasNext來(lái)斷定的。

第二種方法的使用示例如下:

/**
 * 本示例表示從1開(kāi)始組裝一個(gè)序列,第一個(gè)是1,第二個(gè)是1+1即2,第三個(gè)是2+1即3..,直接10時(shí)中止;
 * 也可簡(jiǎn)化成以下形式:
 *  Stream.iterate(1,
 *  n -> n <= 10,
 *  n -> n+1).forEach(System.out::println);
 * 寫(xiě)成以下方式是為簡(jiǎn)化理解
 */
Stream.iterate(1,
  new Predicate<Integer>() {
   @Override
   public boolean test(Integer integer) {
    return integer <= 10;
   }
  },
 new UnaryOperator<Integer>() {
  @Override
  public Integer apply(Integer integer) {
   return integer+1;
  }
}).forEach(System.out::println);

e. 通過(guò)Stream中的generate方法創(chuàng)建

與iterate中創(chuàng)建無(wú)限元素的Stream類(lèi)似,不過(guò)它的每個(gè)元素與前一元素?zé)o關(guān),且生成的是一個(gè)無(wú)序的隊(duì)列。也就是說(shuō)每一個(gè)元素都可以隨機(jī)生成。因此一般用來(lái)創(chuàng)建常量的Stream以及隨機(jī)的Stream等。

示例如下:

/**
 * 隨機(jī)生成10個(gè)Double元素的Stream并將其打印
 */
Stream.generate(new Supplier<Double>() {
 @Override
 public Double get() {
  return Math.random();
 }
}).limit(10).forEach(System.out::println);

//上述寫(xiě)法可以簡(jiǎn)化成以下寫(xiě)法:
Stream.generate(() -> Math.random()).limit(10).forEach(System.out::println);

f. 通過(guò)Stream中的concat方法連接兩個(gè)Stream對(duì)象生成新的Stream對(duì)象

這個(gè)比較好理解不再贅述。

3.1.2 Stream對(duì)象的使用

Stream對(duì)象提供多個(gè)非常有用的方法,這些方法可以分成兩類(lèi):

中間操作:將原始的Stream轉(zhuǎn)換成另外一個(gè)Stream;如filter返回的是過(guò)濾后的Stream。

終端操作:產(chǎn)生的是一個(gè)結(jié)果或者其它的復(fù)合操作;如count或者forEach操作。

其清單如下所示,方法的具體說(shuō)明及使用示例見(jiàn)后文。

所有中間操作

方法 說(shuō)明
sequential 返回一個(gè)相等的串行的Stream對(duì)象,如果原Stream對(duì)象已經(jīng)是串行就可能會(huì)返回原對(duì)象
parallel 返回一個(gè)相等的并行的Stream對(duì)象,如果原Stream對(duì)象已經(jīng)是并行的就會(huì)返回原對(duì)象
unordered 返回一個(gè)不關(guān)心順序的Stream對(duì)象,如果原對(duì)象已經(jīng)是這類(lèi)型的對(duì)象就會(huì)返回原對(duì)象
onClose 返回一個(gè)相等的Steam對(duì)象,同時(shí)新的Stream對(duì)象在執(zhí)行Close方法時(shí)會(huì)調(diào)用傳入的Runnable對(duì)象
close 關(guān)閉Stream對(duì)象
filter 元素過(guò)濾:對(duì)Stream對(duì)象按指定的Predicate進(jìn)行過(guò)濾,返回的Stream對(duì)象中僅包含未被過(guò)濾的元素
map 元素一對(duì)一轉(zhuǎn)換:使用傳入的Function對(duì)象對(duì)Stream中的所有元素進(jìn)行處理,返回的Stream對(duì)象中的元素為原元素處理后的結(jié)果
mapToInt 元素一對(duì)一轉(zhuǎn)換:將原Stream中的使用傳入的IntFunction加工后返回一個(gè)IntStream對(duì)象
flatMap 元素一對(duì)多轉(zhuǎn)換:對(duì)原Stream中的所有元素進(jìn)行操作,每個(gè)元素會(huì)有一個(gè)或者多個(gè)結(jié)果,然后將返回的所有元素組合成一個(gè)統(tǒng)一的Stream并返回;
distinct 去重:返回一個(gè)去重后的Stream對(duì)象
sorted 排序:返回排序后的Stream對(duì)象
peek 使用傳入的Consumer對(duì)象對(duì)所有元素進(jìn)行消費(fèi)后,返回一個(gè)新的包含所有原來(lái)元素的Stream對(duì)象
limit 獲取有限個(gè)元素組成新的Stream對(duì)象返回
skip 拋棄前指定個(gè)元素后使用剩下的元素組成新的Stream返回
takeWhile 如果Stream是有序的(Ordered),那么返回最長(zhǎng)命中序列(符合傳入的Predicate的最長(zhǎng)命中序列)組成的Stream;如果是無(wú)序的,那么返回的是所有符合傳入的Predicate的元素序列組成的Stream。
dropWhile 與takeWhile相反,如果是有序的,返回除最長(zhǎng)命中序列外的所有元素組成的Stream;如果是無(wú)序的,返回所有未命中的元素組成的Stream。

所有終端操作

方法 說(shuō)明
iterator 返回Stream中所有對(duì)象的迭代器;
spliterator 返回對(duì)所有對(duì)象進(jìn)行的spliterator對(duì)象
forEach 對(duì)所有元素進(jìn)行迭代處理,無(wú)返回值
forEachOrdered 按Stream的Encounter所決定的序列進(jìn)行迭代處理,無(wú)返回值
toArray 返回所有元素的數(shù)組
reduce 使用一個(gè)初始化的值,與Stream中的元素一一做傳入的二合運(yùn)算后返回最終的值。每與一個(gè)元素做運(yùn)算后的結(jié)果,再與下一個(gè)元素做運(yùn)算。它不保證會(huì)按序列執(zhí)行整個(gè)過(guò)程。
collect 根據(jù)傳入?yún)?shù)做相關(guān)匯聚計(jì)算
min 返回所有元素中最小值的Optional對(duì)象;如果Stream中無(wú)任何元素,那么返回的Optional對(duì)象為Empty
max 與Min相反
count 所有元素個(gè)數(shù)
anyMatch 只要其中有一個(gè)元素滿(mǎn)足傳入的Predicate時(shí)返回True,否則返回False
allMatch 所有元素均滿(mǎn)足傳入的Predicate時(shí)返回True,否則False
noneMatch 所有元素均不滿(mǎn)足傳入的Predicate時(shí)返回True,否則False
findFirst 返回第一個(gè)元素的Optioanl對(duì)象;如果無(wú)元素返回的是空的Optional; 如果Stream是無(wú)序的,那么任何元素都可能被返回。
findAny 返回任意一個(gè)元素的Optional對(duì)象,如果無(wú)元素返回的是空的Optioanl。
isParallel 判斷是否當(dāng)前Stream對(duì)象是并行的

下面就幾個(gè)比較常用的方法舉例說(shuō)明其用法:

3.1.2.1 filter

用于對(duì)Stream中的元素進(jìn)行過(guò)濾,返回一個(gè)過(guò)濾后的Stream

其方法定義如下:

Stream<T> filter(Predicate<? super T> predicate);

使用示例:

Stream<String> s = Stream.of("test", "t1", "t2", "teeeee", "aaaa");
//查找所有包含t的元素并進(jìn)行打印
s.filter(n -> n.contains("t")).forEach(System.out::println);

3.1.2.2 map

元素一對(duì)一轉(zhuǎn)換。

它接收一個(gè)Funcation參數(shù),用其對(duì)Stream中的所有元素進(jìn)行處理,返回的Stream對(duì)象中的元素為Function對(duì)原元素處理后的結(jié)果

其方法定義如下:

<R> Stream<R> map(Function<? super T, ? extends R> mapper);

示例,假設(shè)我們要將一個(gè)String類(lèi)型的Stream對(duì)象中的每個(gè)元素添加相同的后綴.txt,如a變成a.txt,其寫(xiě)法如下:

Stream<String> s = Stream.of("test", "t1", "t2", "teeeee", "aaaa");

s.map(n -> n.concat(".txt")).forEach(System.out::println);

3.1.2.3 flatMap

元素一對(duì)多轉(zhuǎn)換:對(duì)原Stream中的所有元素使用傳入的Function進(jìn)行處理,每個(gè)元素經(jīng)過(guò)處理后生成一個(gè)多個(gè)元素的Stream對(duì)象,然后將返回的所有Stream對(duì)象中的所有元素組合成一個(gè)統(tǒng)一的Stream并返回;

方法定義如下:

<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);

示例,假設(shè)要對(duì)一個(gè)String類(lèi)型的Stream進(jìn)行處理,將每一個(gè)元素的拆分成單個(gè)字母,并打印:

Stream<String> s = Stream.of("test", "t1", "t2", "teeeee", "aaaa");

s.flatMap(n -> Stream.of(n.split(""))).forEach(System.out::println);

3.1.2.4 takeWhile

方法定義如下:

default Stream<T> takeWhile(Predicate<? super T> predicate)

如果Stream是有序的(Ordered),那么返回最長(zhǎng)命中序列(符合傳入的Predicate的最長(zhǎng)命中序列)組成的Stream;如果是無(wú)序的,那么返回的是所有符合傳入的Predicate的元素序列組成的Stream。

與Filter有點(diǎn)類(lèi)似,不同的地方就在當(dāng)Stream是有序時(shí),返回的只是最長(zhǎng)命中序列。

如以下示例,通過(guò)takeWhile查找”test”, “t1”, “t2”, “teeeee”, “aaaa”, “taaa”這幾個(gè)元素中包含t的最長(zhǎng)命中序列:

Stream<String> s = Stream.of("test", "t1", "t2", "teeeee", "aaaa", "taaa");
//以下結(jié)果將打印: "test", "t1", "t2", "teeeee",最后的那個(gè)taaa不會(huì)進(jìn)行打印 
s.takeWhile(n -> n.contains("t")).forEach(System.out::println);

3.1.2.5 dropWhile

與takeWhile相反,如果是有序的,返回除最長(zhǎng)命中序列外的所有元素組成的Stream;如果是無(wú)序的,返回所有未命中的元素組成的Stream;其定義如下:

default Stream<T> dropWhile(Predicate<? super T> predicate)

如以下示例,通過(guò)dropWhile刪除”test”, “t1”, “t2”, “teeeee”, “aaaa”, “taaa”這幾個(gè)元素中包含t的最長(zhǎng)命中序列:

Stream<String> s = Stream.of("test", "t1", "t2", "teeeee", "aaaa", "taaa");
//以下結(jié)果將打印:"aaaa", "taaa"  
s.dropWhile(n -> n.contains("t")).forEach(System.out::println);

3.1.2.6 reduce與collect

關(guān)于reduce與collect由于功能較為復(fù)雜,在后續(xù)將進(jìn)行單獨(dú)分析與學(xué)習(xí),此處暫不涉及。

3.2 Optional

用于簡(jiǎn)化Java中對(duì)空值的判斷處理,以防止出現(xiàn)各種空指針異常。

Optional實(shí)際上是對(duì)一個(gè)變量進(jìn)行封裝,它包含有一個(gè)屬性value,實(shí)際上就是這個(gè)變量的值。

3.2.1 Optional對(duì)象創(chuàng)建

它的構(gòu)造函數(shù)都是private類(lèi)型的,因此要初始化一個(gè)Optional的對(duì)象無(wú)法通過(guò)其構(gòu)造函數(shù)進(jìn)行創(chuàng)建。它提供了一系列的靜態(tài)方法用于構(gòu)建Optional對(duì)象:

3.2.1.1 empty

用于創(chuàng)建一個(gè)空的Optional對(duì)象;其value屬性為Null。

如:

Optional o = Optional.empty();

3.2.1.2 of

根據(jù)傳入的值構(gòu)建一個(gè)Optional對(duì)象;

傳入的值必須是非空值,否則如果傳入的值為空值,則會(huì)拋出空指針異常。

使用:

o = Optional.of("test");

3.2.1.3 ofNullable

根據(jù)傳入值構(gòu)建一個(gè)Optional對(duì)象

傳入的值可以是空值,如果傳入的值是空值,則與empty返回的結(jié)果是一樣的。

3.2.2 方法

Optional包含以下方法:

方法名 說(shuō)明
get 獲取Value的值,如果Value值是空值,則會(huì)拋出NoSuchElementException異常;因此返回的Value值無(wú)需再做空值判斷,只要沒(méi)有拋出異常,都會(huì)是非空值。
isPresent Value是否為空值的判斷;
ifPresent 當(dāng)Value不為空時(shí),執(zhí)行傳入的Consumer;
ifPresentOrElse Value不為空時(shí),執(zhí)行傳入的Consumer;否則執(zhí)行傳入的Runnable對(duì)象;
filter 當(dāng)Value為空或者傳入的Predicate對(duì)象調(diào)用test(value)返回False時(shí),返回Empty對(duì)象;否則返回當(dāng)前的Optional對(duì)象
map 一對(duì)一轉(zhuǎn)換:當(dāng)Value為空時(shí)返回Empty對(duì)象,否則返回傳入的Function執(zhí)行apply(value)后的結(jié)果組裝的Optional對(duì)象;
flatMap 一對(duì)多轉(zhuǎn)換:當(dāng)Value為空時(shí)返回Empty對(duì)象,否則傳入的Function執(zhí)行apply(value)后返回的結(jié)果(其返回結(jié)果直接是Optional對(duì)象)
or 如果Value不為空,則返回當(dāng)前的Optional對(duì)象;否則,返回傳入的Supplier生成的Optional對(duì)象;
stream 如果Value為空,返回Stream對(duì)象的Empty值;否則返回Stream.of(value)的Stream對(duì)象;
orElse Value不為空則返回Value,否則返回傳入的值;
orElseGet Value不為空則返回Value,否則返回傳入的Supplier生成的值;
orElseThrow Value不為空則返回Value,否則拋出Supplier中生成的異常對(duì)象;

3.2.3 使用場(chǎng)景

常用的使用場(chǎng)景如下:

3.2.3.1 判斷結(jié)果不為空后使用

如某個(gè)函數(shù)可能會(huì)返回空值,以往的做法:

String s = test();
if (null != s) {
 System.out.println(s);
}

現(xiàn)在的寫(xiě)法就可以是:

Optional<String> s = Optional.ofNullable(test());

s.ifPresent(System.out::println);

乍一看代碼復(fù)雜度上差不多甚至是略有提升;那為什么要這么做呢?

一般情況下,我們?cè)谑褂媚骋粋€(gè)函數(shù)返回值時(shí),要做的第一步就是去分析這個(gè)函數(shù)是否會(huì)返回空值;如果沒(méi)有進(jìn)行分析或者分析的結(jié)果出現(xiàn)偏差,導(dǎo)致函數(shù)會(huì)拋出空值而沒(méi)有做檢測(cè),那么就會(huì)相應(yīng)的拋出空指針異常!

而有了Optional后,在我們不確定時(shí)就可以不用去做這個(gè)檢測(cè)了,所有的檢測(cè)Optional對(duì)象都幫忙我們完成,我們要做的就是按上述方式去處理。

3.2.3.2 變量為空時(shí)提供默認(rèn)值

如要判斷某個(gè)變量為空時(shí)使用提供的值,然后再針對(duì)這個(gè)變量做某種運(yùn)算;

以往做法:

if (null == s) {
 s = "test";
}
System.out.println(s);

現(xiàn)在的做法:

Optional<String> o = Optional.ofNullable(s);

System.out.println(o.orElse("test"));

3.2.3.3 變量為空時(shí)拋出異常,否則使用

以往寫(xiě)法:

if (null == s) {
 throw new Exception("test");
}
System.out.println(s);

現(xiàn)在寫(xiě)法:

Optional<String> o = Optional.ofNullable(s);

System.out.println(o.orElseThrow(()->new Exception("test")));

其它場(chǎng)景待補(bǔ)充。

以上這篇java8新特性之stream的collect實(shí)戰(zhàn)教程就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • JavaScript base64 與 File 之間的互轉(zhuǎn)(操作方法)

    JavaScript base64 與 File 之間的互轉(zhuǎn)(操作方法)

    在JavaScript 中,可以使用 Blob 對(duì)象將 base64 字符串轉(zhuǎn)換為 File 對(duì)象,這篇文章主要介紹了JavaScript base64 與 File之間的互轉(zhuǎn),需要的朋友可以參考下
    2024-05-05
  • Mybatis Limit實(shí)現(xiàn)分頁(yè)功能

    Mybatis Limit實(shí)現(xiàn)分頁(yè)功能

    這篇文章主要介紹了Mybatis Limit實(shí)現(xiàn)分頁(yè)功能,使用Limit實(shí)現(xiàn)分頁(yè)可以減少數(shù)據(jù)的處理量,本文通過(guò)代碼講解的非常詳細(xì),需要的朋友可以參考下
    2021-04-04
  • Java中I/O流讀取數(shù)據(jù)不完整的問(wèn)題解決

    Java中I/O流讀取數(shù)據(jù)不完整的問(wèn)題解決

    本文主要介紹了ava中I/O流讀取數(shù)據(jù)不完整的問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-05-05
  • 解決Java中properties文件編碼問(wèn)題

    解決Java中properties文件編碼問(wèn)題

    大家好,本篇文章主要講的是解決Java中properties文件編碼問(wèn)題,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話(huà)記得收藏一下
    2022-02-02
  • Java實(shí)現(xiàn)帶頭結(jié)點(diǎn)的單鏈表

    Java實(shí)現(xiàn)帶頭結(jié)點(diǎn)的單鏈表

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)帶頭結(jié)點(diǎn)的單鏈表,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-09-09
  • Java中讀寫(xiě)鎖ReadWriteLock的原理與應(yīng)用詳解

    Java中讀寫(xiě)鎖ReadWriteLock的原理與應(yīng)用詳解

    Java并發(fā)編程提供了讀寫(xiě)鎖,主要用于讀多寫(xiě)少的場(chǎng)景,今天我們就重點(diǎn)來(lái)講解讀寫(xiě)鎖ReadWriteLock的原理與應(yīng)用場(chǎng)景,感興趣的可以了解一下
    2022-09-09
  • JavaWeb項(xiàng)目Servlet無(wú)法訪(fǎng)問(wèn)問(wèn)題解決

    JavaWeb項(xiàng)目Servlet無(wú)法訪(fǎng)問(wèn)問(wèn)題解決

    這篇文章主要介紹了JavaWeb項(xiàng)目Servlet無(wú)法訪(fǎng)問(wèn)問(wèn)題解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-11-11
  • mybatis-plus排除非表中字段的操作

    mybatis-plus排除非表中字段的操作

    這篇文章主要介紹了mybatis-plus排除非表中字段的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-12-12
  • Java接口返回省市區(qū)樹(shù)形結(jié)構(gòu)的實(shí)現(xiàn)

    Java接口返回省市區(qū)樹(shù)形結(jié)構(gòu)的實(shí)現(xiàn)

    本文主要介紹了Java接口返回省市區(qū)樹(shù)形結(jié)構(gòu)的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-01-01
  • 解決Maven依賴(lài)沖突的方法

    解決Maven依賴(lài)沖突的方法

    本文主要介紹了解決Maven依賴(lài)沖突的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-05-05

最新評(píng)論

陇川县| 濮阳县| 安龙县| 西充县| 乌拉特前旗| 甘洛县| 宁南县| 潞西市| 江口县| 射洪县| 马山县| 开阳县| 太康县| 隆子县| 仁寿县| 安乡县| 潞西市| 苗栗县| 德昌县| 长乐市| 科技| 陵川县| 会泽县| 项城市| 宣武区| 南溪县| 民和| 理塘县| 泽州县| 丰顺县| 玉山县| 本溪市| 兴文县| 古交市| 秭归县| 长治市| 周口市| 岳池县| 容城县| 易门县| 舟曲县|