欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

首頁綜合 正文
目錄

柚子快報邀請碼778899分享:數(shù)據(jù)庫 Stream 流式編程

柚子快報邀請碼778899分享:數(shù)據(jù)庫 Stream 流式編程

http://yzkb.51969.com/

優(yōu)質(zhì)博文:IT-BLOG-CN

大家都知道可以將Collection類轉(zhuǎn)化成流Stream進行操作(Map并不能創(chuàng)建流),代碼變得簡約流暢。我們先看下流的幾個特點: 1、流并不存儲元素。這些元素可能存儲在底層的集合中,或者是按需生成。 2、流的操作不會修改其數(shù)據(jù)元素,而是生成一個新的流。 3、流的操作是盡可能惰性執(zhí)行的。這意味著直至需要其結(jié)果時,操作才會執(zhí)行。

一、創(chuàng)建流

負責新建一個Stream流,大多數(shù)都是基于現(xiàn)有的數(shù)組、List、Set、Map等集合創(chuàng)建新的Stream。

stream()

創(chuàng)建一個stream串行流對象。

CR時可優(yōu)化的代碼片段:

public List toListByOldTicketNo(List sourceList) {

List targetList = Lists.newArrayListWithExpectedSize(sourceList.size());

for (SFltStudent source : sourceList) {

SFltStudent target = new SFltStudent();

target.setTicketNo(source.getOldTicketNo());

target.setFlightAgency(source.getFlightAgency());

targetList.add(target);

}

return targetList;

}

代碼優(yōu)化:這里sourceList如果數(shù)據(jù)量很大時,也可以考慮parallel stream。這里主要是想通過stream提高代碼簡潔性和可讀性。

public List toListByOldTicketNo(List sourceList) {

return sourceList.stream()

.map(source -> {

SFltStudent target = new SFltStudent();

target.setTicketNo(source.getOldTicketNo());

target.setFlightAgency(source.getFlightAgency());

return target;

})

.collect(Collectors.toList());

}

parallelStream()

創(chuàng)建一個可并行執(zhí)行的stream流對象??梢杂行Ю糜嬎銠C的多CPU硬件,提升邏輯的執(zhí)行速度。將一整個stream劃分為多個片段,然后對各個分片流并行執(zhí)行處理邏輯,最后將各個分片流的執(zhí)行結(jié)果匯總為一個整體流。

::: tip 如果遇到耗時的操作,或者大量IO的操作,或者有線程sleep的操作一定要避免使用并行流。

并行流場景效率會比迭代器逐個循環(huán)更高。 :::

查看parallelStream的源碼發(fā)現(xiàn)parallel Stream底層是將任務進行了切分,最終將任務傳遞給了jdk8自帶的“全局”ForkJoinPool線程池。在Fork-Join中,比如一個擁有4個線程的ForkJoinPool線程池,有一個任務隊列,一個大的任務切分出的子任務會提交到線程池的任務隊列中,4個線程從任務隊列中獲取任務執(zhí)行,哪個線程執(zhí)行的任務快,哪個線程執(zhí)行的任務就多,只有隊列中沒有任務線程才是空閑的,這就是工作竊取。

/**

* @return a possibly parallel {@code Stream} over the elements in this == parallelStream()并不一定返回一個并行流,有可能parallelStream()全是由主線程順序執(zhí)行的。

* collection

* @since 1.8

*/

default Stream parallelStream() {

return StreamSupport.stream(spliterator(), true);

}

注意:parallelStream和整個java進程共用ForkJoinPool:如果直接使用parallelStream().foreach會默認使用全局的ForkJoinPool,而這樣就會導致當前程序很多地方共用同一個線程池,包括gc相關(guān)操作在內(nèi),所以一旦任務隊列中滿了之后,就會出現(xiàn)阻塞的情況,導致整個程序的只要當前使用ForkJoinPool的地方都會出現(xiàn)問題。

CR時可優(yōu)化的代碼片段: :并發(fā)獲取接口數(shù)據(jù),進行業(yè)務處理,對共享數(shù)據(jù)的修改需要考慮多線程安全問題。

List errorMessageList = Collections.synchronizedList(new ArrayList<>());

List errorProductOrderIds = Collections.synchronizedList(new ArrayList<>());

infos.parallelStream()

.filter(XStudentOrderInfo::getChecked)

.map(XStudentOrderInfo::getProductOrderID)

.filter(StringUtils::isNotBlank)

.distinct()

.allMatch(productOrderId -> {

XRefundResponse response = xStudentCancelSoa.xStudentClassOrder(getXStudentRequest(eid, refundInfo, productOrderId));

boolean isSuccess = response.getResponseStatus() != null

&& response.getResponseStatus().ack == AckCodeType.Success

&& response.isIsSuccess() != null

&& response.isIsSuccess();

if (!isSuccess && StringUtils.isNotBlank(response.getMessage())) {

errorMessageList.add(response.getMessage());

errorProductOrderIds.add(productOrderId);

}

return isSuccess;

})

);

代碼優(yōu)化:將復雜的條件判斷提取到processOrder方法中,使主流處理邏輯更加簡潔和易讀。

List errorMessageList = Collections.synchronizedList(new ArrayList<>());

List errorProductOrderIds = Collections.synchronizedList(new ArrayList<>());

boolean allSuccess = infos.parallelStream()

.filter(XStudentOrderInfo::getChecked)

.map(XStudentOrderInfo::getProductOrderID)

.filter(StringUtils::isNotBlank)

.distinct()

.allMatch(productOrderId -> processOrder(productOrderId, errorMessageList, errorProductOrderIds));

private boolean processOrder(String productOrderId, List errorMessageList, List errorProductOrderIds) {

XRefundResponse response = xStudentCancelSoa.xStudentClassOrder(getXStudentRequest(eid, refundInfo, productOrderId));

boolean isSuccess = response.getResponseStatus() != null

&& response.getResponseStatus().ack == AckCodeType.Success

&& Boolean.TRUE.equals(response.isIsSuccess());

if (!isSuccess && StringUtils.isNotBlank(response.getMessage())) {

errorMessageList.add(response.getMessage());

errorProductOrderIds.add(productOrderId);

}

return isSuccess;

}

Stream.of()

通過給定的一系列元素創(chuàng)建一個新的stream串行流對象。

二、Stream 中間處理

輸入Stream對象,輸出一個新的Stream對象,中間管道操作可以進行疊加。

規(guī)范

CR時發(fā)現(xiàn)不規(guī)范的流式編程如下:

issueBillList.stream().map(IssueBillDO::getIssueBillId).collect(Collectors.toList());

根據(jù)代碼規(guī)范,在代碼中使用鏈式調(diào)用時,為了提高代碼的可讀性和維護性,建議在方法鏈的每個方法調(diào)用之間進行換行。這樣可以使代碼更容易閱讀和理解。

List issueBillIds = issueBillList.stream()

.map(IssueBillDO::getIssueBillId)

.collect(Collectors.toList());

filter()

按照條件過濾符合要求的元素,返回新的stream流。

CR時可優(yōu)化的代碼片段: .filter多個過濾條件并存,存在一定的優(yōu)化空間。編程如下:

.filter(r -> StringUtilsExt.compareIgnoreSpaceAndCaps(r.getPassengerName(), trace.getPassengerName())

&& StringUtilsExt.compareIgnoreSpaceAndCaps(r.getFlight(), trace.getFlightNo())

&& StringUtilsExt.compareIgnoreSpaceAndCaps(r.getDPort(), trace.getDport()))

......

建議根據(jù)業(yè)務將它們拆分為多個.filter方法調(diào)用可以提高代碼的可讀性和可維護性。但是需要注意每個.filter調(diào)用都會遍歷一次流中的元素。如果流非常大,多個.filter調(diào)用可能會帶來性能開銷。同時如果條件之間存在邏輯依賴關(guān)系,拆分成多個.filter調(diào)用可能會導致邏輯錯誤。例如,如果某個條件的結(jié)果會影響另一個條件的判斷,拆分可能會破壞這種依賴關(guān)系。雖然拆分可以提高某些情況下的可讀性,但如果條件本身很簡單,拆分反而會使代碼顯得冗長和復雜。

具體大家根據(jù)自己的業(yè)務特點進行選擇

方案一:如果條件非常復雜,或者你希望每個條件都能單獨清晰地表達,可以拆分成多個.filter方法

.filter(r -> StringUtilsExt.compareIgnoreSpaceAndCaps(r.getPassengerName(), trace.getTripInfo().getPassengerName()))

.filter(r -> StringUtilsExt.compareIgnoreSpaceAndCaps(r.getFlight(), trace.getTripInfo().getFlightNo()))

.filter(r -> StringUtilsExt.compareIgnoreSpaceAndCaps(r.getDPort(), trace.getTripInfo().getDport()))

方案二:如果條件邏輯非常復雜,考慮將條件封裝到一個輔助方法中,這樣代碼會更加清晰

.filter(r -> matchesTraceInfo(r, trace.getTripInfo()))

private boolean matchesTraceInfo(Record r, TripInfo tripInfo) {

return StringUtilsExt.compareIgnoreSpaceAndCaps(r.getPassengerName(), tripInfo.getPassengerName()) &&

StringUtilsExt.compareIgnoreSpaceAndCaps(r.getFlight(), tripInfo.getFlightNo()) &&

StringUtilsExt.compareIgnoreSpaceAndCaps(r.getDPort(), tripInfo.getDport());

}

map()

將已有元素轉(zhuǎn)換為另一個對象類型,一對一邏輯,返回新的stream流。

List ids = Arrays.asList("A1", "A2", "A3");

// 使用流操作

List results = ids.stream()

.map(id -> {

id.replace("A","B");

return id;

})

.collect(Collectors.toList());

System.out.println(results);

執(zhí)行之后,會發(fā)現(xiàn)每一個元素都被轉(zhuǎn)換為對應新的元素,但是前后總元素個數(shù)是一致的:

B1

B2

B3

下面的代碼因?qū)ap和filter功能的混淆,導致代碼執(zhí)行解決與預期不符,最終出現(xiàn)生產(chǎn)故障。

if (response != null && response.isPresent() && response.isPresent().get().getResult() != null) {

ResultType resultType = response.isPresent().get().getResult();

resultType.getResultList().stream()

.map(p -> matchChildResult(p) && p.getCode == CODE_404)

.findFirst().ifPresent(result -> {

logger.build("childdata", "fail:).info();

if (ConfigFunc.getBoolean("childIntercept", false)) {

throw new ResultException("fail);

}

});

原因:如果使用map這段代碼會返回一個List的列表,應該不是開發(fā)者想要的。而且,只要respose返回了結(jié)果,那么map就會返回一個List列表,這個列表可能為:[true,false,......]等等,開發(fā)者應該要的是滿足條件才拋出錯誤的,但是生產(chǎn)應該是只要respose返回了結(jié)果code無論是不是404都會拋錯。導致線上系統(tǒng)異常,訂單下跌。

flatMap()

將已有元素轉(zhuǎn)換為另一個對象類型,一對多邏輯,即原來一個元素對象可能會轉(zhuǎn)換為1個或者多個新類型的元素,返回新的stream流。

案例:

List sentences = Arrays.asList("B1 B2","B3 B4");

// 使用流操作

List results2 = sentences.stream()

.flatMap(sentence -> Arrays.stream(sentence.split(" ")))

.collect(Collectors.toList());

System.out.println(results2);

執(zhí)行之后,會發(fā)現(xiàn)每一個元素都被轉(zhuǎn)換為多個新的元素:

B1

B2

B3

B4

flatMap操作是先將每個元素進行處理并返回一個新的Stream,然后將多個Stream展開合并為了一個完整的新的Stream,如下:

CR時可優(yōu)化的代碼片段: 應用場景為List中的對象中包含List列表

List allMaterialList = specialEventInfoForPageList.stream()

.filter(Objects::nonNull)

.filter(p -> CollectionUtils.isNotEmpty(p.getMaterialInfoList()))

.flatMap(p -> p.getMaterialInfoList().stream().filter(Objects::nonNull))

.collect(Collectors.toList());

代碼優(yōu)化:提前檢查p.getMaterialInfoList()是否為空的處理,CollectionUtils和Collectors被頻繁使用,可以進行靜態(tài)導入以簡化代碼。

List allMaterialList = specialEventInfoForPageList.stream()

.filter(p -> p != null && isNotEmpty(p.getMaterialInfoList()))

.flatMap(p -> p.getMaterialInfoList().stream())

.filter(Objects::nonNull)

.collect(toList());

limit()

僅保留集合前面指定個數(shù)的元素,返回新的stream流。

Stream integerStream = Arrays.stream({1, 2, 3})

.limit(2);

System.out.println(Arrays.toString(integerStream.toArray())); // [1, 2]

skip()

跳過集合前面指定個數(shù)的元素,返回新的stream流。

Stream integerStream = Arrays.stream({1, 2, 3});

.skip(2);

System.out.println(Arrays.toString(integerStream.toArray())); // [3]

concat()

將兩個流的數(shù)據(jù)合并起來為1個新的流,返回新的stream流。

distinct()

對Stream中所有元素進行去重,返回新的stream流。

**CR`時可優(yōu)化的代碼片段:**

submitReiEntityList = model.getReibursementInfo().getSubmitReiEntityList().stream()

.map(ReibursementApplyOrderInfo::getOrderId)

.distinct()

.collect(Collectors.toList());

這里主要說一個思想,是否可以將需要distinct的集合轉(zhuǎn)換為Set進行存儲,提高查找效率。

sorted()

對stream中所有的元素按照指定規(guī)則進行排序,返回新的stream流。

這里主要看一下目前存在的寫法

CR片段一

wordSet1 = wordSet.stream().sorted(new Comparator() {

@Override

public int compare(String o1, String o2) {

return o2.length() - o1.length();

}

}).collect(Collectors.toList());

CR片段二

List sortedLogs = logs.stream()

.sorted((RescheduleLog i1, RescheduleLog i2) -> i2.getRecordTime().compareTo(i1.getRecordTime()))

.collect(Collectors.toList());

CR片段三:上面的片段可以按照該規(guī)范,簡化代碼。

List orderedDescList = rescheduleIssueBills.stream()

.sorted(Comparator.comparing(RescheduleIssueBill::getIssueBillID).reversed())

.collect(Collectors.toList());

CR片段四

List orderedDescList = rescheduleIssueBills

.stream()

.sorted(Comparator.comparing(RescheduleIssueBill::getIssueBillID).reversed())

.collect(Collectors.toList());

代碼優(yōu)化:如果不需要保留原始列表的順序,可以直接對original進行排序,避免創(chuàng)建額外的心列表。

original.sort(Comparator.comparing(SegmentInfo::getSortedSequence));

peek()

對stream流中的每個元素進行逐個遍歷處理,返回處理后的stream流。意味著peek只能作為管道中途的一個處理步驟,而沒法直接執(zhí)行得到結(jié)果,其后面必須還要有其它終止操作的時候才會被執(zhí)行;而foreach作為無返回值的終止方法,則可以直接執(zhí)行相關(guān)操作。

CR過程中使用peek的代碼,peek么有問題,但是代碼還是有一定的優(yōu)化空間。

List auditSuccessList = auditInfoList.stream()

.filter(auditInfo -> AllianceAuditStatusEnum.AUDIT_SUCCESS.getValue().equals(auditInfo.getAuditStatus()))

.peek(auditInfo -> {

Integer customKey = idxAtomic.getAndUpdate(idx -> idx + NumberUtils.INTEGER_ONE);

auditInfo.setCustomKey(customKey);

})

.collect(Collectors.toList());

我們給一個更優(yōu)雅的代碼:

List auditSuccessList = auditInfoList.stream()

.filter(auditInfo -> AllianceAuditStatusEnum.AUDIT_SUCCESS.getValue().equals(auditInfo.getAuditStatus()))

.peek(auditInfo -> auditInfo.setCustomKey(idxAtomic.getAndIncrement()))

.collect(Collectors.toList());

三、終止Stream

通過終止管道操作之后,Stream流將會結(jié)束,最后可能會執(zhí)行某些邏輯處理,或者是按照要求返回某些執(zhí)行后的結(jié)果數(shù)據(jù)。

count()

返回stream處理后最終的元素個數(shù)。

CR時可優(yōu)化的代碼片段:

groupByDataType.entrySet().stream()

.allMatch(entry -> entry.getValue().stream()

.map(DiscountInfo::getDeductionAmount)

.distinct()

.count() == 1);

代碼優(yōu)化:上述代碼distinct與count結(jié)合使用時,可以使用Set與length()方法實現(xiàn),但是這里使用count和distinct可能從業(yè)務上理解更為接近,所以具體需要根據(jù)業(yè)務場景決定。

boolean allMatch = groupByDataType.entrySet().stream()

.allMatch(entry -> entry.getValue().stream()

.map(DiscountInfo::getDeductionAmount)

.collect(Collectors.toSet())

.size() == 1);

但是這里可以根據(jù)allMatch的特性上進行優(yōu)化,只要找到一個不滿足條件的金額,就提前返回false提交性能。

boolean allMatch = groupByDataType.entrySet().stream()

.allMatch(entry -> {

Set deductionAmounts = entry.getValue().stream()

.map(DiscountInfo::getDeductionAmount)

.collect(Collectors.toSet());

return deductionAmounts.size() == 1;

});

max()

返回stream處理后的元素最大值。

CR時可優(yōu)化的代碼片段:

files.stream()

.mapToInt(UploadRetireMaterialInfoType::getBatchNo)

.max()

.getAsInt();

代碼優(yōu)化:這里主要的問題是,再調(diào)用getAsInt()方法時,一定要判斷下是否存在,否則回報異常。

OptionalInt maxBatchNoOptional = files.stream()

.mapToInt(UploadRetireMaterialInfoType::getBatchNo)

.max();

if (maxBatchNoOptional.isPresent()) {

int maxBatchNo = maxBatchNoOptional.getAsInt();

} else {

......

}

min()

返回stream處理后的元素最小值。

CR過程中發(fā)現(xiàn)可以使用min()方法進行優(yōu)化的代碼片段

List sortRefundDetails = refundDetails.stream()

.sorted(Comparator.comparing(SFltticketStudentByairlineMy::getSequence))

.collect(toList());

SFltticketStudentByairlineMy firstSeqTicketNo = sortRefundDetails.get(0);

優(yōu)化后代碼如下:

refundDetails.stream()

.min(Comparator.comparing(SFltticketStudentByairlineMy::getSequence));

findFirst()

找到第一個符合條件的元素時則終止流處理。

優(yōu)化片段一:

CR時發(fā)現(xiàn).findFirst()返回Optional可以繼續(xù)進行業(yè)務處理,存在一定的優(yōu)化空間。代碼如下:

oc.getOrderInfoList().stream()

.filter(f -> (StringUtilsExt.compareIgnoreSpaceAndCaps(f.getFlight(), lastTrip.getFlightNo())

......)

.findFirst().orElse(null);

if (lastFlight != null) {

......

}

可以在findFirst()方法后繼續(xù)執(zhí)行操作,而不需要單獨的if (lastFlight != null)語句。流式編程提供了ifPresent方法,可以讓你在找到符合條件的元素時執(zhí)行某些操作。這樣使代碼更加簡潔和流暢,不需要顯式地進行空值檢查。

oc.getOrderInfoList().stream()

.filter(f -> (StringUtilsExt.compareIgnoreSpaceAndCaps(f.getFlight(), lastTrip.getFlightNo())

......)

.findFirst()

.ifPresent(lastFlight -> {

// 在這里執(zhí)行你需要的操作

// 例如:

// System.out.println("Found flight: " + lastFlight);

});

優(yōu)化片段二:

對.findFirst()方法使用存在優(yōu)化空間

List sortRefundDetails = refundDetails.stream()

.sorted(Comparator.comparing(SFltticketStudentByairlineMy::getSequence))

.collect(toList());

SFltticketStudentByairlineMy firstSeqTicketNo = sortRefundDetails.get(0);

使用.findFirst()方法獲取第一個符合要求的元素即可。當然這個代碼還存在優(yōu)化空間。

SFltticketStudentByairlineMy firstSeqTicketNo = refundDetails.stream()

.sorted(Comparator.comparing(SFltticketStudentByairlineMy::getSequence))

.collect(toList())

.findFirst();

findAny()

找到任何一個符合條件的元素時則退出流處理,這個對于串行流時與findFirst相同,對于并行流時比較高效,任何分片中找到都會終止后續(xù)計算邏輯。

CR時可優(yōu)化的代碼片段:

orderInfo.getRefundInfoList().stream()

.filter(a -> MATERIAL_SUPPLEMENT_FLAG.equals(a.getKey()) && TRUE_VALUE.equals(a.getValue()))

.findAny()

.isPresent();

優(yōu)化代碼:返回的是一個boolean類型,可以直接使用anyMatch()

boolean isPresent = orderInfo.getRefundOrderFlagInfoList().stream()

.anyMatch(a -> MATERIAL_SUPPLEMENT_FLAG.equals(a.getKey()) && TRUE_VALUE.equals(a.getValue()));

anyMatch()

返回一個boolean值,類似于isContains(),用于判斷是否有符合條件的元素。

我們也會將寫的標準的代碼推薦給大家

boolean isAgencyModeOrder = CollectionsUtil.isNotEmpty(orderAlibabaCartList)

&& orderAlibabaCartList.stream()

.filter(s -> Objects.equals(s.getBookType(), BookingTypeConstants.TICKET_PLUS_X_ORDER))

.anyMatch(s -> Objects.equals(s.getPaymentVersion(), PaymentVersionConstants.PAYMENT_AGENCY));

allMatch()

返回一個boolean值,用于判斷是否所有元素都符合條件。

在CR中發(fā)現(xiàn)可以優(yōu)化的代碼:在流操作中fucLi部分存在優(yōu)化空間。

private Stream doFilter(List sourceList) {

return sourceList.stream()

.filter(

source -> {

List> fucLi =

buildFilterConditions(source);

return fucLi.stream().allMatch(Supplier::get);

});

}

代碼是一個過濾方法,它將一個List轉(zhuǎn)換為一個Stream,并根據(jù)某些條件對其進行過濾。具體來說,它使用了buildFilterConditions方法來生成一組Supplier,然后檢查這些條件是否都滿足。如果所有條件都滿足,則保留該元素。

優(yōu)化后的代碼:將fucLi變量內(nèi)聯(lián)到filter方法中,減少了不必要的局部變量聲明,使代碼更加簡潔。

private Stream doFilter(List sourceList) {

return sourceList.stream()

.filter(source -> buildFilterConditions(source).stream().allMatch(Supplier::get));

}

noneMatch()

返回一個boolean值, 用于判斷是否所有元素都不符合條件。

CR時可優(yōu)化的代碼片段:

boolean userBehaviorsCheck = filterRecordList.stream().noneMatch(record -> IntegerUtils.compare(record.getPageCode(), 201));

collect()

將流轉(zhuǎn)換為指定的類型,通過Collectors進行指定。

toArray()

將流轉(zhuǎn)換為數(shù)組。

iterator()

將流轉(zhuǎn)換為Iterator對象。

CR時可優(yōu)化的代碼片段:

Iterator iterator = passengers.iterator();

while (iterator.hasNext()) {

M_RelateAliPassenger passenger = iterator.next();

boolean matched = passengers2.stream()

.anyMatch(p -> p.getPassengerName() != null && p.getPassengerName().equalsIgnoreCase(passenger.getPassengerName()));

if (!matched) {

iterator.remove();

}

}

優(yōu)化后的代碼:主要任務是從passengers列表中移除那些在passengers2列表中沒有匹配的乘客??梢酝ㄟ^集合操作來簡化和優(yōu)化這段代碼。

passengers.removeIf(passenger ->

passengers2.stream()

.noneMatch(p -> p.getPassengerName() != null

&& p.getPassengerName().equalsIgnoreCase(passenger.getPassengerName()))

);

foreach()

無返回值,對元素進行逐個遍歷,然后執(zhí)行給定的處理邏輯。foreach()操作與parallelStream()搭配使用時,必須保證是線程安全的。也不要直接使用默認的線程池。

CR時可優(yōu)化的代碼片段:

parameterList.forEach(param -> orderIds.append(param.getOrderID()).append(","));

優(yōu)化后的代碼:Collectors.joining(",")最適合做上述的工作,應該是首先想到的。

String orderIds = parameterList.stream()

.map(param -> param.getOrderID())

.collect(Collectors.joining(","));

常見問題

一旦一個Stream被執(zhí)行了終止操作之后,后續(xù)便不可以再讀這個流執(zhí)行其他的操作了,否則會報錯,看下面示例:

public void testHandleStreamAfterClosed() {

List ids = Arrays.asList("205", "10", "308", "49", "627", "193", "111", "193");

Stream stream = ids.stream().filter(s -> s.length() > 2);

// 統(tǒng)計stream操作后剩余的元素個數(shù)

System.out.println(stream.count());

System.out.println("-----下面會報錯-----");

// 判斷是否有元素值等于205

try {

System.out.println(stream.anyMatch("205"::equals));

} catch (Exception e) {

e.printStackTrace();

System.out.println(e.toString());

}

System.out.println("-----上面會報錯-----");

}

結(jié)果:

-----下面會報錯-----

java.lang.IllegalStateException: stream has already been operated upon or closed

-----上面會報錯-----

java.lang.IllegalStateException: stream has already been operated upon or closed

at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:229)

at java.util.stream.ReferencePipeline.anyMatch(ReferencePipeline.java:516)

at Solution_0908.main(Solution_0908.java:55)

因為stream已經(jīng)被執(zhí)行count()終止方法了,所以對stream再執(zhí)行anyMatch方法的時候,就會報錯stream has already been operated upon or closed,這一點在使用的時候需要特別注意。

四、collect方法

獲取一個集合類的結(jié)果對象,比如List、Set或者HashMap等。

Collectors.toList()

List collectList = normalOfferModelList

.stream()

.filter(offer -> offer.getCate1LevelId().equals("11"))

.collect(Collectors.toList());

Collectors.toSet()

Set collectSet = normalOfferModelList

.stream()

.filter(offer -> offer.getCate1LevelId().equals("22"))

.collect(Collectors.toSet());

Collectors.toMap

CodeReview 時發(fā)現(xiàn)的問題:沒有考慮key重復問題。

Arrays.stream(clazz.getDeclaredFields())

.collect(Collectors.toMap(r -> r.getName().toLowerCase(), r -> r));

優(yōu)化后的代碼:Function.identity()是java.util.function.Function接口中的一個靜態(tài)方法。它總是返回一個其輸入?yún)?shù)的函數(shù)。這在需要傳遞一個不做任何變換的函數(shù)時非常有用。Function.identity()等價于上面的r -> r。(k1, k2) -> k2就是解決重復key的問題,當存在重復key時使用最后一個key。

Arrays.stream(clazz.getDeclaredFields())

.collect(NormalOfferModel::getName, Function.identity(), (k1, k2) -> k2));

Collectors.joining

List ids = Arrays.asList("205", "10", "308", "49", "627", "193", "111", "193");

String joinResult = ids.stream().collect(Collectors.joining(","));

Collectors.averagingInt

List ids = Arrays.asList(10, 20, 30, 40, 50);

// 計算平均值

Double average = ids.stream().collect(Collectors.averagingInt(value -> value));

Collectors.summarizingInt

List ids = Arrays.asList(10, 20, 30, 40, 50);

// 數(shù)據(jù)統(tǒng)計信息

IntSummaryStatistics summary = ids.stream().collect(Collectors.summarizingInt(value -> value));

Optional 類

ifPresent(Consumer action)

如果Optional中包含值,執(zhí)行給定的Consumer操作,否則什么也不做。常用于簡化代碼,避免顯式的空值檢查。

isPresent()

檢查Optional中是否包含值。如果包含值,返回true,否則返回false。

get()

如果Optional中包含值,返回該值;否則拋出NoSuchElementException。這個方法不推薦頻繁使用,因為它違背了Optional的初衷,即避免顯式的空值檢查和異常處理。

orElse(T other)

如果Optional中包含值,返回該值;否則返回other。常用于提供默認值。

orElseGet(Supplier other)

如果Optional中包含值,返回該值;否則通過調(diào)用Supplier獲取一個默認值。與orElse不同的是,Supplier只有在需要時才會被調(diào)用,因此適用于生成默認值開銷較大的情況。

isEmpty()

檢查Optional中是否為空。如果為空,返回true,否則返回false。

orElseThrow()

如果Optional中包含值,返回該值;否則拋出NoSuchElementException。

optional.orElseThrow(() -> new IllegalArgumentException("Value is absent"));

orElseThrow(Supplier exceptionSupplier)

如果Optional中包含值,返回該值;否則通過Supplier拋出指定的異常。

filter(Predicate predicate)

如果Optional中包含值,并且該值滿足給定的謂詞,返回一個包含該值的Optional;否則返回一個空的Optional。常用于條件過濾。

Optional filtered = optional.filter(value -> value.length() > 3);

map(Function mapper)

如果Optional中包含值,應用給定的函數(shù)并返回一個包含映射結(jié)果的Optional;否則返回一個空的Optional。常用于鏈式調(diào)用。

Optional length = optional.map(String::length);

flatMap(Function> mapper)

與map類似,但mapper函數(shù)返回的是一個Optional對象,并且不會對返回的Optional進行嵌套。

Optional name = optional.flatMap(value -> Optional.of("Processed " + value));

柚子快報邀請碼778899分享:數(shù)據(jù)庫 Stream 流式編程

http://yzkb.51969.com/

推薦鏈接

評論可見,查看隱藏內(nèi)容

本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。

轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。

本文鏈接:http://gantiao.com.cn/post/19472475.html

發(fā)布評論

您暫未設(shè)置收款碼

請在主題配置——文章設(shè)置里上傳

掃描二維碼手機訪問

文章目錄