java Stream操作轉(zhuǎn)換方法
流創(chuàng)建
| 方法 | |
|---|---|
| 集合 | Collection.stream/parllelStream |
| 數(shù)組 | Arrays.stream |
| 數(shù)字Stream | IntStream/LongStream.range/rangeClosed/Random.inis/longs/doubles |
| 自己創(chuàng)建 | stream.generate/iterate |
1、list 轉(zhuǎn) map
工作中,我們經(jīng)常遇到list轉(zhuǎn)map的案例。Collectors.toMap就可以把一個(gè)list數(shù)組轉(zhuǎn)成一個(gè)Map。代碼如下:
public class TestLambda {
public static void main(String[] args) {
List<UserInfo> userInfoList = new ArrayList<>();
userInfoList.add(new UserInfo(1L, "測(cè)試源碼", 18));
userInfoList.add(new UserInfo(2L, "程序員淘淘", 27));
userInfoList.add(new UserInfo(2L, "打代碼的淘淘", 26));
/**
* list 轉(zhuǎn) map
* 使用Collectors.toMap的時(shí)候,如果有可以重復(fù)會(huì)報(bào)錯(cuò),所以需要加(k1, k2) -> k1
* (k1, k2) -> k1 表示,如果有重復(fù)的key,則保留第一個(gè),舍棄第二個(gè)
*/
Map<Long, UserInfo> userInfoMap = userInfoList.stream().collect(Collectors.toMap(UserInfo::getUserId, userInfo -> userInfo, (k1, k2) -> k1));
userInfoMap.values().forEach(a->System.out.println(a.getUserName()));
}
}類似的,還有Collectors.toList()、Collectors.toSet(),表示把對(duì)應(yīng)的流轉(zhuǎn)化為list或者Set。
2、filter()過濾
從數(shù)組集合中,過濾掉不符合條件的元素,留下符合條件的元素。
List<UserInfo> userInfoList = new ArrayList<>(); userInfoList.add(new UserInfo(1L, "測(cè)試源碼", 18)); userInfoList.add(new UserInfo(2L, "程序員淘淘", 27)); userInfoList.add(new UserInfo(3L, "打代碼的淘淘", 26)); /** * filter 過濾,留下超過18歲的用戶 */ List<UserInfo> userInfoResultList = userInfoList.stream().filter(user -> user.getAge() > 18).collect(Collectors.toList()); userInfoResultList.forEach(a -> System.out.println(a.getUserName())); //運(yùn)行結(jié)果 程序員淘淘 打代碼的淘淘
3、foreach遍歷
foreach 遍歷list,遍歷map,真的很絲滑。
/**
* forEach 遍歷集合List列表
*/
List<String> userNameList = Arrays.asList("測(cè)試源碼", "程序員淘淘", "艿艿");
userNameList.forEach(System.out::println);
HashMap<String, String> hashMap = new HashMap<>();
hashMap.put("號(hào)碼你", "測(cè)試源碼");
hashMap.put("職業(yè)", "程序員淘淘");
hashMap.put("昵稱", "艿艿");
/**
* forEach 遍歷集合Map
*/
hashMap.forEach((k, v) -> System.out.println(k + ":\t" + v));
//運(yùn)行結(jié)果
測(cè)試源碼
程序員淘淘
打代碼的淘淘
職業(yè): 程序員淘淘
號(hào)碼你: 測(cè)試源碼
昵稱: 艿艿4、groupingBy 分組
提到分組,相信大家都會(huì)想起SQL的group by。我們經(jīng)常需要一個(gè)List做分組操作。比如,按城市分組用戶。在Java8之前,是這么實(shí)現(xiàn)的:
List<UserInfo> originUserInfoList = new ArrayList<>();
originUserInfoList.add(new UserInfo(1L, "測(cè)試源碼", 18,"深圳"));
originUserInfoList.add(new UserInfo(3L, "打代碼的淘淘", 26,"湛江"));
originUserInfoList.add(new UserInfo(2L, "程序員淘淘", 27,"深圳"));
Map<String, List<UserInfo>> result = new HashMap<>();
for (UserInfo userInfo : originUserInfoList) {
String city = userInfo.getCity();
List<UserInfo> userInfos = result.get(city);
if (userInfos == null) {
userInfos = new ArrayList<>();
result.put(city, userInfos);
}
userInfos.add(userInfo);
}而使用Java8的groupingBy分組器,清爽無比:
Map<String, List<UserInfo>> result = originUserInfoList.stream() .collect(Collectors.groupingBy(UserInfo::getCity));
5、sorted+Comparator 排序
工作中,排序的需求比較多,使用sorted+Comparator排序,真的很香。
List<UserInfo> userInfoList = new ArrayList<>();
userInfoList.add(new UserInfo(1L, "測(cè)試源碼", 18));
userInfoList.add(new UserInfo(3L, "打代碼的淘淘", 26));
userInfoList.add(new UserInfo(2L, "程序員淘淘", 27));
/**
* sorted + Comparator.comparing 排序列表,
*/
userInfoList = userInfoList.stream().sorted(Comparator.comparing(UserInfo::getAge)).collect(Collectors.toList());
userInfoList.forEach(a -> System.out.println(a.toString()));
System.out.println("開始降序排序");
/**
* 如果想降序排序,則可以使用加reversed()
*/
userInfoList = userInfoList.stream().sorted(Comparator.comparing(UserInfo::getAge).reversed()).collect(Collectors.toList());
userInfoList.forEach(a -> System.out.println(a.toString()));
//運(yùn)行結(jié)果
UserInfo{userId=1, userName='測(cè)試源碼', age=18}
UserInfo{userId=3, userName='打代碼的淘淘', age=26}
UserInfo{userId=2, userName='程序員淘淘', age=27}
開始降序排序
UserInfo{userId=2, userName='程序員淘淘', age=27}
UserInfo{userId=3, userName='打代碼的淘淘', age=26}
UserInfo{userId=1, userName='測(cè)試源碼', age=18}
-=-----------------------------------------------------------------
private static void test04(){
// 按工資升序排序(自然排序)
List<String> newList = personList.stream().sorted(Comparator.comparing(Person::getSalary)).map(Person::getName)
.collect(Collectors.toList());
// 按工資倒序排序
List<String> newList2 = personList.stream().sorted(Comparator.comparing(Person::getSalary).reversed())
.map(Person::getName).collect(Collectors.toList());
// 先按工資再按年齡升序排序
List<String> newList3 = personList.stream()
.sorted(Comparator.comparing(Person::getSalary).thenComparing(Person::getAge)).map(Person::getName)
.collect(Collectors.toList());
// 先按工資再按年齡自定義排序(降序)
List<String> newList4 = personList.stream().sorted((p1, p2) -> {
if (p1.getSalary() == p2.getSalary()) {
return p2.getAge() - p1.getAge();
} else {
return p2.getSalary() - p1.getSalary();
}
}).map(Person::getName).collect(Collectors.toList());
System.out.println("按工資升序排序:" + newList);
System.out.println("按工資降序排序:" + newList2);
System.out.println("先按工資再按年齡升序排序:" + newList3);
System.out.println("先按工資再按年齡自定義降序排序:" + newList4);
}6、distinct去重
distinct可以去除重復(fù)的元素:
List<String> list = Arrays.asList("A", "B", "F", "A", "C");
List<String> temp = list.stream().distinct().collect(Collectors.toList());
temp.forEach(System.out::println);7、findFirst返回第一個(gè)
findFirst 很多業(yè)務(wù)場(chǎng)景,我們只需要返回集合的第一個(gè)元素即可:
List<String> list = Arrays.asList("A", "B", "F", "A", "C");
list.stream().findFirst().ifPresent(System.out::println);8、anyMatch 是否至少匹配一個(gè)元素
anyMatch 檢查流是否包含至少一個(gè)滿足給定謂詞的元素。
Stream<String> stream = Stream.of("A", "B", "C", "D");
boolean match = stream.anyMatch(s -> s.contains("C"));
System.out.println(match);
//輸出
true9、allMatch 匹配所有元素
allMatch 檢查流是否所有都滿足給定謂詞的元素。
Stream<String> stream = Stream.of("A", "B", "C", "D");
boolean match = stream.allMatch(s -> s.contains("C"));
System.out.println(match);
//輸出
false10、map 轉(zhuǎn)換
map方法可以幫我們做元素轉(zhuǎn)換,比如一個(gè)元素所有字母轉(zhuǎn)化為大寫,又或者把獲取一個(gè)元素對(duì)象的某個(gè)屬性,demo如下:
List<String> list = Arrays.asList("jay", "tianluo");
//轉(zhuǎn)化為大寫
List<String> upperCaselist = list.stream().map(String::toUpperCase).collect(Collectors.toList());
upperCaselist.forEach(System.out::println);11、Reduce
Reduce可以合并流的元素,并生成一個(gè)值
int sum = Stream.of(1, 2, 3, 4).reduce(0, (a, b) -> a + b);
System.out.println(sum);
/**
* 求Integer集合的元素之和、乘積和最大值
*
*/
private static void test13() {
List<Integer> list = Arrays.asList(1, 2, 3, 4);
//求和
Optional<Integer> reduce = list.stream().reduce((x,y) -> x+ y);
System.out.println("求和:"+reduce);
//求積
Optional<Integer> reduce2 = list.stream().reduce((x,y) -> x * y);
System.out.println("求積:"+reduce2);
//求最大值
Optional<Integer> reduce3 = list.stream().reduce((x,y) -> x>y?x:y);
System.out.println("求最大值:"+reduce3);
}
/*
* 求所有員工的工資之和和最高工資
*/
private static void test14() {
initPerson();
Optional<Integer> reduce = personList.stream().map(Person :: getSalary).reduce(Integer::sum);
Optional<Integer> reduce2 = personList.stream().map(Person :: getSalary).reduce(Integer::max);
System.out.println("工資之和:"+reduce);
System.out.println("最高工資:"+reduce2);
}12、peek 打印個(gè)日志
peek()方法是一個(gè)中間Stream操作,有時(shí)候我們可以使用peek來打印日志。
List<String> result = Stream.of("程序員淘淘", "測(cè)試源碼", "打代碼的淘淘")
.filter(a -> a.contains("芋艿"))
.peek(a -> System.out.println("關(guān)注號(hào)碼你:" + a)).collect(Collectors.toList());
System.out.println(result);
//運(yùn)行結(jié)果
關(guān)注號(hào)碼你:程序員淘淘
關(guān)注號(hào)碼你:測(cè)試源碼
[程序員淘淘, 測(cè)試源碼]13、Max,Min 最大最小
使用lambda流求最大,最小值,非常方便。
List<UserInfo> userInfoList = new ArrayList<>();
userInfoList.add(new UserInfo(1L, "測(cè)試源碼", 18));
userInfoList.add(new UserInfo(3L, "打代碼的淘淘", 26));
userInfoList.add(new UserInfo(2L, "程序員淘淘", 27));
Optional<UserInfo> maxAgeUserInfoOpt = userInfoList.stream().max(Comparator.comparing(UserInfo::getAge));
maxAgeUserInfoOpt.ifPresent(userInfo -> System.out.println("max age user:" + userInfo));
Optional<UserInfo> minAgeUserInfoOpt = userInfoList.stream().min(Comparator.comparing(UserInfo::getAge));
minAgeUserInfoOpt.ifPresent(userInfo -> System.out.println("min age user:" + userInfo));
//運(yùn)行結(jié)果
max age user:UserInfo{userId=2, userName='程序員淘淘', age=27}
min age user:UserInfo{userId=1, userName='測(cè)試源碼', age=18}14、count 統(tǒng)計(jì)
一般count()表示獲取流數(shù)據(jù)元素總數(shù)。
List<UserInfo> userInfoList = new ArrayList<>();
userInfoList.add(new UserInfo(1L, "測(cè)試源碼", 18));
userInfoList.add(new UserInfo(3L, "打代碼的淘淘", 26));
userInfoList.add(new UserInfo(2L, "程序員淘淘", 27));
long count = userInfoList.stream().filter(user -> user.getAge() > 18).count();
System.out.println("大于18歲的用戶:" + count);
//輸出
大于18歲的用戶:2
/**
* 統(tǒng)計(jì)員工人數(shù)、平均工資、工資總額、最高工資
*/
private static void test01(){
//統(tǒng)計(jì)員工人數(shù)
Long count = personList.stream().collect(Collectors.counting());
//求平均工資
Double average = personList.stream().collect(Collectors.averagingDouble(Person::getSalary));
//求最高工資
Optional<Integer> max = personList.stream().map(Person::getSalary).collect(Collectors.maxBy(Integer::compare));
//求工資之和
Integer sum = personList.stream().collect(Collectors.summingInt(Person::getSalary));
//一次性統(tǒng)計(jì)所有信息
DoubleSummaryStatistics collect = personList.stream().collect(Collectors.summarizingDouble(Person::getSalary));
System.out.println("統(tǒng)計(jì)員工人數(shù):"+count);
System.out.println("求平均工資:"+average);
System.out.println("求最高工資:"+max);
System.out.println("求工資之和:"+sum);
System.out.println("一次性統(tǒng)計(jì)所有信息:"+collect);
}15、提取/組合
流也可以進(jìn)行合并、去重、限制、跳過等操作。
private static void test05(){
String[] arr1 = { "a", "b", "c", "d" };
String[] arr2 = { "d", "e", "f", "g" };
Stream<String> stream1 = Stream.of(arr1);
Stream<String> stream2 = Stream.of(arr2);
// concat:合并兩個(gè)流 distinct:去重
List<String> newList = Stream.concat(stream1, stream2).distinct().collect(Collectors.toList());
// limit:限制從流中獲得前n個(gè)數(shù)據(jù)
List<Integer> collect = Stream.iterate(1, x -> x + 2).limit(10).collect(Collectors.toList());
// skip:跳過前n個(gè)數(shù)據(jù)
List<Integer> collect2 = Stream.iterate(1, x -> x + 2).skip(1).limit(5).collect(Collectors.toList());
System.out.println("流合并:" + newList);
System.out.println("limit:" + collect);
System.out.println("skip:" + collect2);
}16、連接joining
joining可以將stream中的元素用特定的連接符(沒有的話,則直接連接)連接成一個(gè)字符串。
List<Integer> list = Arrays.asList(7, 6, 9, 3, 10, 2, 1);
String collect = list.stream().map(String::valueOf).collect(Collectors.joining(","));
System.out.println(collect);
7,6,9,3,10,2,117、常用函數(shù)式接口
其實(shí)lambda離不開函數(shù)式接口,我們來看下JDK8常用的幾個(gè)函數(shù)式接口:
Function<T, R>(轉(zhuǎn)換型): 接受一個(gè)輸入?yún)?shù),返回一個(gè)結(jié)果Consumer<T>(消費(fèi)型): 接收一個(gè)輸入?yún)?shù),并且無返回操作Predicate<T>(判斷型): 接收一個(gè)輸入?yún)?shù),并且返回布爾值結(jié)果Supplier<T>(供給型): 無參數(shù),返回結(jié)果
Function<T, R> 是一個(gè)功能轉(zhuǎn)換型的接口,可以把將一種類型的數(shù)據(jù)轉(zhuǎn)化為另外一種類型的數(shù)據(jù)
private void testFunction() {
//獲取每個(gè)字符串的長(zhǎng)度,并且返回
Function<String, Integer> function = String::length;
Stream<String> stream = Stream.of("程序員淘淘", "測(cè)試源碼", "打代碼的淘淘");
Stream<Integer> resultStream = stream.map(function);
resultStream.forEach(System.out::println);
}Consumer<T>是一個(gè)消費(fèi)性接口,通過傳入?yún)?shù),并且無返回的操作
private void testComsumer() {
//獲取每個(gè)字符串的長(zhǎng)度,并且返回
Consumer<String> comsumer = System.out::println;
Stream<String> stream = Stream.of("程序員淘淘", "測(cè)試源碼", "打代碼的淘淘");
stream.forEach(comsumer);
}Predicate<T>是一個(gè)判斷型接口,并且返回布爾值結(jié)果.
private void testPredicate() {
//獲取每個(gè)字符串的長(zhǎng)度,并且返回
Predicate<Integer> predicate = a -> a > 18;
UserInfo userInfo = new UserInfo(2L, "程序員淘淘", 27);
System.out.println(predicate.test(userInfo.getAge()));
}Supplier<T>是一個(gè)供給型接口,無參數(shù),有返回結(jié)果。
private void testSupplier() {
Supplier<Integer> supplier = () -> Integer.valueOf("666");
System.out.println(supplier.get());
}這幾個(gè)函數(shù)在日常開發(fā)中,也是可以靈活應(yīng)用的,比如我們DAO操作完數(shù)據(jù)庫,是會(huì)有個(gè)result的整型結(jié)果返回。我們就可以用Supplier<T>來統(tǒng)一判斷是否操作成功。如下:
private void saveDb(Supplier<Integer> supplier) {
if (supplier.get() > 0) {
System.out.println("插入數(shù)據(jù)庫成功");
}else{
System.out.println("插入數(shù)據(jù)庫失敗");
}
}
@Test
public void add() throws Exception {
Course course=new Course();
course.setCname("java");
course.setUserId(100L);
course.setCstatus("Normal");
saveDb(() -> courseMapper.insert(course));
}到此這篇關(guān)于java Stream操作轉(zhuǎn)換方法的文章就介紹到這了,更多相關(guān)java Stream操作內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JAVA中StringBuffer與String的區(qū)別解析
這篇文章主要介紹了JAVA中StringBuffer與String的區(qū)別解析,需要的朋友可以參考下2014-02-02
SpringBoot打印系統(tǒng)執(zhí)行的sql語句及日志配置指南
這篇文章主要給大家介紹了關(guān)于SpringBoot打印系統(tǒng)執(zhí)行的sql語句及日志配置的相關(guān)資料,在Java SpringBoot項(xiàng)目中如果使用了Mybatis框架,默認(rèn)情況下執(zhí)行的所有SQL操作都不會(huì)打印日志,需要的朋友可以參考下2023-10-10
springboot用戶數(shù)據(jù)修改的詳細(xì)實(shí)現(xiàn)
用戶管理功能作為所有的系統(tǒng)是必不可少的一部分,下面這篇文章主要給大家介紹了關(guān)于springboot用戶數(shù)據(jù)修改的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-04-04
Spring+Hibernate+Struts(SSH)框架整合實(shí)戰(zhàn)
SSH是 struts+spring+hibernate的一個(gè)集成框架,是目前比較流行的一種Web應(yīng)用程序開源框架。本篇文章主要介紹了Spring+Hibernate+Struts(SSH)框架整合實(shí)戰(zhàn),非常具有實(shí)用價(jià)值,需要的朋友可以參考下2018-04-04
Spring動(dòng)態(tài)注冊(cè)多數(shù)據(jù)源的實(shí)現(xiàn)方法
這篇文章主要介紹了Spring動(dòng)態(tài)注冊(cè)多數(shù)據(jù)源的實(shí)現(xiàn)方法,小編覺的挺不錯(cuò)的,現(xiàn)分享到腳本之家平臺(tái),需要的朋友可以參考下2018-01-01
spring中定時(shí)任務(wù)taskScheduler的詳細(xì)介紹
這篇文章主要介紹了spring中定時(shí)任務(wù)taskScheduler的相關(guān)資料,文中通過示例代碼介紹的很詳細(xì),相信對(duì)大家具有一定的參考價(jià)值,有需要的朋友們下面來一起看看吧。2017-02-02

