5分鐘讓你快速掌握java8 stream常用開(kāi)發(fā)技巧
前言
如果有些朋友以前沒(méi)有使用過(guò)java8 stream這種鏈?zhǔn)骄幊谭绞阶鲩_(kāi)發(fā),想學(xué)習(xí)一下。
如果有些朋友只學(xué)習(xí)了一部分用法,想學(xué)習(xí)更多。
如果有些朋友想看看有沒(méi)有好的示例適用于實(shí)際工作當(dāng)中。
那么恭喜你,這篇文章非常適合你。
首先,我們一起看看stream的繼承關(guān)系:
Stream、IntStream、LongStream、DoubleStream的父接口都是BaseStream。BaseStream的四個(gè)子接口方法都差不多,只是IntStream、LongStream、DoubleStream直接存儲(chǔ)基本類型,可以避免自動(dòng)裝/拆箱,效率會(huì)更高一些。但是,我們實(shí)際上使用Stream更多一些。
我們?cè)倏纯磗tream的工作流程圖:
為什么要學(xué)stream的鏈?zhǔn)骄幊谭绞?br />
業(yè)務(wù)需求1:指定一個(gè)字符串?dāng)?shù)組,找出里面相同的元素,并且統(tǒng)計(jì)重復(fù)的次數(shù)。
我們以前大概是這樣做的:
public class CountTest { @Test public void testCount1() { List<String> list = Lists.newArrayList("a", "b", "ab", "abc", "a", "ab", "a", "abcd", "bd", "abc"); Map<String, Long> countMap = new HashMap<>(); for (String data : list) { Long aLong = countMap.get(data); if (Objects.isNull(aLong)) { countMap.put(data, 1L); } else { countMap.put(data, ++aLong); } } countMap.forEach((key, value) -> System.out.println("key:" + key + " value:" + value)); } }
執(zhí)行結(jié)果:
key:a value:3
key:ab value:2
key:b value:1
key:bd value:1
key:abc value:2
key:abcd value:1
我們?cè)倏纯慈绻胘ava8的stream可以怎么做:
public class CountTest { @Test public void testCount2() { List<String> list = Lists.newArrayList("a", "b", "ab", "abc", "a", "ab", "a", "abcd", "bd", "abc"); Map<String, Long> countMap = list.stream().collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); countMap.forEach((key, value) -> System.out.println("key:" + key + " value:" + value)); } }
執(zhí)行結(jié)果:
key:a value:3
key:ab value:2
key:b value:1
key:bd value:1
key:abc value:2
key:abcd value:1
我們可以看到testCount1和testCount2執(zhí)行結(jié)果相同,僅僅一行代碼:
Map<String, Long> countMap = list.stream().collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
就可以實(shí)現(xiàn)上面testCount1中多行代碼的邏輯。
業(yè)務(wù)需求2:從一個(gè)指定的字符串?dāng)?shù)組中,查找指定的字符串是否存在
我們以前大概是這樣做的:
public class FindTest { @Test public void testFind1() { String findStr = "bd"; List<String> list = Lists.newArrayList("a", "b", "ab", "abc", "a", "ab", "a", "abcd", "bd", "abc"); boolean match = false; for (String data : list) { if (data.equals(findStr)) { match = true; break; } } //結(jié)果:match:true System.out.println("match:" + match); } }
我們?cè)倏纯慈绻胘ava8的stream可以怎么做:
public class MatchTest { @Test public void testFind2() { String findStr = "bd"; List<String> list = Lists.newArrayList("a", "b", "ab", "abc", "a", "ab", "a", "abcd", "bd", "abc"); boolean match = list.stream().anyMatch(x -> x.equals(findStr)); //結(jié)果:match:true System.out.println("match:" + match); } }
我們可以看到調(diào)用testFind1和testFind2方法執(zhí)行結(jié)果也是一樣的。但是,用java8 stream的語(yǔ)法,又只用一行代碼就完成功能了,真棒。
java8 stream超詳細(xì)用法指南
stream的操作符大體上分為兩種:中間操作符和終止操作符
中間操作:
1.filter(T-> boolean)
過(guò)濾數(shù)據(jù),保留 boolean 為 true 的元素,返回一個(gè)集合
public class FilterTest { @Test public void testFilter() { List<Integer> list = Lists.newArrayList(20, 23, 25, 28, 30, 33, 37, 40); //從指定數(shù)據(jù)集合中過(guò)濾出大于等于30的數(shù)據(jù)集合 List<Integer> collect = list.stream().filter(x -> x >= 30).collect(Collectors.toList()); //結(jié)果:[33, 37, 40] System.out.println(collect); } }
collect(Collectors.toList())可以把流轉(zhuǎn)換為 List 類型,collect實(shí)際上是一個(gè)終止操作。
2.map(T -> R)
轉(zhuǎn)換操作符,可以做數(shù)據(jù)轉(zhuǎn)換,比如:把字符串轉(zhuǎn)換成int、long、double,或者把一個(gè)實(shí)體轉(zhuǎn)換成另外一個(gè)實(shí)體。包含:map,mapToInt、mapToLong、mapToDouble
public class MapTest { @Test public void testMap() { List<String> list = Lists.newArrayList("1", "2", "3", "4", "5", "6"); List<Long> collect1 = list.stream().map(x -> Long.parseLong(x)).collect(Collectors.toList()); //結(jié)果:[1, 2, 3, 4, 5, 6] System.out.println(collect1); //結(jié)果:111111 list.stream().mapToInt(x -> x.length()).forEach(System.out::print); System.out.println(""); //結(jié)果:111111 list.stream().mapToLong(x -> x.length()).forEach(System.out::print); System.out.println(""); //結(jié)果:1.01.01.01.01.01.0 list.stream().mapToDouble(x -> x.length()).forEach(System.out::print); } }
3.flatMap(T -> Stream)
將流中的每一個(gè)元素 T 映射為一個(gè)流,再把每一個(gè)流連接成為一個(gè)流
public class FlatMapTest { @Test public void testFlatMap() { List<List<String>> list = new ArrayList<List<String>>(){{ add(Lists.newArrayList("a","b","c")); add(Lists.newArrayList("d","e","f")); add(Lists.newArrayList("j","k","y")); }}; //結(jié)果:[[a, b, c], [d, e, f], [j, k, y]] System.out.println(list); List<String> collect = list.stream().flatMap(List::stream).collect(Collectors.toList()); //結(jié)果:[a, b, c, d, e, f, j, k, y] System.out.println(collect); } }
我們可以看到flatMap可以輕松把字符串的二維數(shù)據(jù)變成一位數(shù)組。
4.distinct
去重,類似于msql中的distinct的作用,底層使用了equals方法做比較。
public class DistinctTest { @Test public void testDistinct() { List<String> list = Lists.newArrayList("a", "b", "ab", "abc", "a", "ab", "a", "abcd", "bd", "abc"); List<String> collect = list.stream().distinct().collect(Collectors.toList()); //結(jié)果:[a, b, ab, abc, abcd, bd] System.out.println(collect); } }
其實(shí),去重還有另外一種辦法,可以用Collectors.toSet(),后面會(huì)講到。
5.sorted
對(duì)元素進(jìn)行排序,前提是實(shí)現(xiàn)Comparable接口,當(dāng)然也可以自定義比較器。
public class SortTest { @Test public void testSort() { List<Integer> list = Lists.newArrayList(5, 3, 7, 1, 4, 6); List<Integer> collect = list.stream().sorted((a, b) -> a.compareTo(b)).collect(Collectors.toList()); //結(jié)果:[1, 3, 4, 5, 6, 7] System.out.println(collect); } }
6.limit
限流操作,有點(diǎn)類似于mysql中的limit功能,比如:有10個(gè)元素,只取前面3個(gè)元素
public class LimitTest { @Test public void testLimit() { List<String> list = Lists.newArrayList("a", "b", "ab", "abc", "a", "ab", "a", "abcd", "bd", "abc"); List<String> collect = list.stream().limit(3).collect(Collectors.toList()); //結(jié)果:[a, b, ab] System.out.println(collect); } }
7.skip
跳過(guò)操作,比如:有個(gè)10個(gè)元素,從第5個(gè)元素開(kāi)始去后面的元素
public class SkipTest { @Test public void testSkip() { List<String> list = Lists.newArrayList("a", "b", "ab", "abc", "a", "ab", "a", "abcd", "bd", "abc"); List<String> collect = list.stream().skip(5).collect(Collectors.toList()); //結(jié)果:[ab, a, abcd, bd, abc] System.out.println(collect); } }
8.peek
挑出操作,
public class PeekTest { @Test public void testPeek() { List<String> list = Lists.newArrayList("a", "b", "ab", "abc", "a", "ab", "a", "abcd", "bd", "abc"); //結(jié)果:abababcaabaabcdbdabc list.stream().peek(x -> x.toUpperCase()).forEach(System.out::print); } }
眼尖的朋友會(huì)發(fā)現(xiàn),進(jìn)行x.toUpperCase()轉(zhuǎn)換為大寫(xiě)功能,但是實(shí)際上沒(méi)有生效。把peek改成map方法試試:
public class PeekTest { @Test public void testPeek() { List<String> list = Lists.newArrayList("a", "b", "ab", "abc", "a", "ab", "a", "abcd", "bd", "abc"); //結(jié)果:ABABABCAABAABCDBDABC list.stream().map(x -> x.toUpperCase()).forEach(System.out::print); } }
我們可以看到,用map操作轉(zhuǎn)換成大寫(xiě)功能生效了,但是用peek操作卻沒(méi)有生效。peek只是對(duì)Stream中的元素進(jìn)行某些操作,但是操作之后的數(shù)據(jù)并不返回到Stream中,所以Stream中的元素還是原來(lái)的元素。
終止操作:
1.forEach
遍歷操作,包含:forEach 和 forEachOrdered
forEach:支持并行處理
forEachOrdered:是按順序處理的,遍歷速度較慢
public class ForEachTest { @Test public void testForEach() { List<String> list = Lists.newArrayList("a", "b", "ab"); //結(jié)果:a b ab list.stream().forEach(x-> System.out.print(x+' ')); System.out.println(""); //可以簡(jiǎn)化 //結(jié)果:a b ab list.forEach(x-> System.out.print(x+' ')); System.out.println(""); //結(jié)果:a b ab list.stream().forEachOrdered(x-> System.out.print(x+' ')); } }
2.collect
收集操作,將所有的元素收集起來(lái),Collectors 提供了非常多收集器。包含:toMap、toSet、toList、joining,groupingBy,maxBy,minBy等操作。
toMap:將數(shù)據(jù)流轉(zhuǎn)換為map,里面包含的元素是用key/value的形式的
toSet:將數(shù)據(jù)流轉(zhuǎn)換為set,里面包含的元素不可重復(fù)
toList:將數(shù)據(jù)流轉(zhuǎn)出為list,里面包含的元素是有序的
joining:拼接字符串
groupingBy:分組,可以將list轉(zhuǎn)換map
couting:統(tǒng)計(jì)元素?cái)?shù)量
maxBy:獲取最大元素
minBy:獲取最小元素
summarizingInt: 匯總int類型的元素,返回IntSummaryStatistics,再調(diào)用具體的方法對(duì)元素進(jìn)行統(tǒng)計(jì):getCount(統(tǒng)計(jì)數(shù)量),getSum(求和),getMin(獲取最小值),getMax(獲取最大值),getAverage(獲取平均值)
summarizingLong:匯總long類型的元素,用法同summarizingInt
summarizingDouble:匯總double類型的元素,用法同summarizingInt
averagingInt:獲取int類型的元素的平均值,返回一個(gè)double類型的數(shù)據(jù)
averagingLong:獲取long類型的元素的平均值,用法同averagingInt
averagingDouble:獲取double類型的元素的平均值,用法同averagingInt
mapping:獲取映射,可以將原始元素的一部分內(nèi)容作為一個(gè)新元素返回
public class CollectTest { @Data @AllArgsConstructor class User { private String name; private Integer age; } @Test public void testCollect() { List<String> list0 = Lists.newArrayList("a", "b", "ab"); Map<String, String> collect0 = list0.stream().collect(Collectors.toMap(String::new, Function.identity())); //結(jié)果:{ab=ab, a=a, b=b} System.out.println(collect0); List<String> list = Lists.newArrayList("a", "b", "ab", "a", "b", "ab"); List<String> collect1 = list.stream().collect(Collectors.toList()); //結(jié)果:[a, b, ab, a, b, ab] System.out.println(collect1); //結(jié)果:[a, ab, b] Set<String> collect2 = list.stream().collect(Collectors.toSet()); System.out.println(collect2); String collect3 = list.stream().collect(Collectors.joining(",")); //結(jié)果:a,b,ab,a,b,ab System.out.println(collect3); Map<String, List<String>> collect4 = list.stream().collect(Collectors.groupingBy(Function.identity())); //結(jié)果:{ab=[ab, ab], a=[a, a], b=[b, b]} System.out.println(collect4); Long collect = list.stream().collect(Collectors.counting()); //結(jié)果:6 System.out.println(collect); String collect5 = list.stream().collect(Collectors.maxBy((a, b) -> a.compareTo(b))).orElse(null); //結(jié)果:b System.out.println(collect5); String collect6 = list.stream().collect(Collectors.minBy((a, b) -> a.compareTo(b))).orElse(null); //結(jié)果:a System.out.println(collect6); List<String> list2 = Lists.newArrayList("2", "3", "5"); IntSummaryStatistics summaryStatistics = list2.stream().collect(Collectors.summarizingInt(x -> Integer.parseInt(x))); long sum = summaryStatistics.getSum(); //結(jié)果:10 System.out.println(sum); Double collect7 = list2.stream().collect(Collectors.averagingInt(x -> Integer.parseInt(x))); //結(jié)果:3.3333333333333335 System.out.println(collect7); List<User> userList = new ArrayList<User>() {{ add(new User("jack",23)); add(new User("james",30)); add(new User("curry",28)); }}; List<String> collect8 = userList.stream().collect(Collectors.mapping(User::getName, Collectors.toList())); //[jack, james, curry] System.out.println(collect8); } }
3.find
查找操作,包含:findFirst、findAny
findFirst:找到第一個(gè),返回的類型為Optional
findAny:使用 stream() 時(shí)找到的是第一個(gè)元素,使用 parallelStream() 并行時(shí)找到的是其中一個(gè)元素,返回的類型為Optional
public class FindOpTest { @Test public void testFindOp() { List<String> list = Lists.newArrayList("a", "b", "ab", "abc", "bc", "ab"); //查找第一匹配的元素 String data1 = list.stream().findFirst().orElse(null); //結(jié)果: a System.out.println(data1); String data2 = list.stream().findAny().orElse(null); //結(jié)果: a System.out.println(data2); } }
4.match
匹配操作,包含:allMatch、anyMatch、noneMatch
allMatch:所有元素都滿足條件,返回boolean類型
anyMatch:任意一個(gè)元素滿足條件,返回boolean類型
noneMatch:所有元素都不滿足條件,返回boolean類型
public class MatchTest { @Test public void testMatch() { List<Integer> list = Lists.newArrayList(2, 3, 5, 7); boolean allMatch = list.stream().allMatch(x -> x > 1); //結(jié)果:true System.out.println(allMatch); boolean allMatch2 = list.stream().allMatch(x -> x > 2); //結(jié)果:false System.out.println(allMatch2); boolean anyMatch = list.stream().anyMatch(x -> x > 2); //結(jié)果:true System.out.println(anyMatch); boolean noneMatch1 = list.stream().noneMatch(x -> x > 5); //結(jié)果:false System.out.println(noneMatch1); boolean noneMatch2 = list.stream().noneMatch(x -> x > 7); //結(jié)果:true System.out.println(noneMatch2); } }
5.count
統(tǒng)計(jì)操作,效果跟調(diào)用集合的size()方法類似
public class CountOpTest { @Test public void testCountOp() { List<String> list = Lists.newArrayList("a", "b", "ab"); long count = list.stream().count(); //結(jié)果:3 System.out.println(count); } }
6.min、max
min:獲取最小值,返回Optional類型的數(shù)據(jù)
max:獲取最大值,返回Optional類型的數(shù)據(jù)
public class MaxMinTest { @Test public void testMaxMin() { List<Integer> list = Lists.newArrayList(2, 3, 5, 7); Optional<Integer> max = list.stream().max((a, b) -> a.compareTo(b)); //結(jié)果:7 System.out.println(max.get()); Optional<Integer> min = list.stream().min((a, b) -> a.compareTo(b)); //結(jié)果:2 System.out.println(min.get()); } }
7.reduce
規(guī)約操作,將整個(gè)數(shù)據(jù)流的值規(guī)約為一個(gè)值,count、min、max底層就是使用reduce。
reduce 操作可以實(shí)現(xiàn)從Stream中生成一個(gè)值,其生成的值不是隨意的,而是根據(jù)指定的計(jì)算模型。
public class ReduceTest { @Test public void testReduce() { List<Integer> list = Lists.newArrayList(2, 3, 5, 7); Integer sum1 = list.stream().reduce(0, Integer::sum); //結(jié)果:17 System.out.println(sum1); Optional<Integer> reduce = list.stream().reduce((a, b) -> a + b); //結(jié)果:17 System.out.println(reduce.get()); Integer max = list.stream().reduce(0, Integer::max); //結(jié)果:7 System.out.println(max); Integer min = list.stream().reduce(0, Integer::min); //結(jié)果:0 System.out.println(min); Optional<Integer> reduce1 = list.stream().reduce((a, b) -> a > b ? b : a); //2 System.out.println(reduce1.get()); } }
8.toArray
數(shù)組操作,將數(shù)據(jù)流的元素轉(zhuǎn)換成數(shù)組。
public class ArrayTest { @Test public void testArray() { List<String> list = Lists.newArrayList("a", "b", "ab"); String[] strings = list.stream().toArray(String[]::new); //結(jié)果:a b ab for (int i = 0; i < strings.length; i++) { System.out.print(strings[i]+" "); } } }
stream和parallelStream的區(qū)別
stream:是單管道,稱其為流,其主要用于集合的邏輯處理。
parallelStream:是多管道,提供了流的并行處理,它是Stream的另一重要特性,其底層使用Fork/Join框架實(shí)現(xiàn)
public class StreamTest { @Test public void testStream() { List<Integer> list = Lists.newArrayList(1,2, 3,4, 5,6, 7); //結(jié)果:1234567 list.stream().forEach(System.out::print); } }
public class ParallelStreamTest { @Test public void testParallelStream() { List<Integer> list = Lists.newArrayList(1,2, 3,4, 5,6, 7); //結(jié)果:5726134 list.parallelStream().forEach(System.out::print); } }
我們可以看到直接使用parallelStream的forEach遍歷數(shù)據(jù),是沒(méi)有順序的。
如果要讓parallelStream遍歷時(shí)有順序怎么辦呢?
public class ParallelStreamTest { @Test public void testParallelStream() { List<Integer> list = Lists.newArrayList(1,2, 3,4, 5,6, 7); //結(jié)果:1234567 list.parallelStream().forEachOrdered(System.out::print); } }
parallelStream的工作原理:
實(shí)際工作中的案例
1.從兩個(gè)集合中找相同的元素。一般用于批量數(shù)據(jù)導(dǎo)入的場(chǎng)景,先查詢出數(shù)據(jù),再批量新增或修改。
public class WorkTest { @Test public void testWork1() { List<String> list1 = Lists.newArrayList("a", "b", "ab"); List<String> list2 = Lists.newArrayList("a", "c", "ab"); List<String> collect = list1.stream() .filter(x -> list2.stream().anyMatch(e -> e.equals(x))) .collect(Collectors.toList()); //結(jié)果:[a, ab] System.out.println(collect); } }
2.有兩個(gè)集合a和b,過(guò)濾出集合a中有,但是集合b中沒(méi)有的元素。這種情況可以使用在假如指定一個(gè)id集合,根據(jù)id集合從數(shù)據(jù)庫(kù)中查詢出數(shù)據(jù)集合,再根據(jù)id集合過(guò)濾出數(shù)據(jù)集合中不存在的id,這些id就是需要新增的。
@Test public void testWork2() { List<String> list1 = Lists.newArrayList("a", "b", "ab"); List<String> list2 = Lists.newArrayList("a", "c", "ab"); List<String> collect = list1.stream() .filter(x -> list2.stream().noneMatch(e -> e.equals(x))) .collect(Collectors.toList()); //結(jié)果:[b] System.out.println(collect); }
3.根據(jù)條件過(guò)濾數(shù)據(jù),并且去重做數(shù)據(jù)轉(zhuǎn)換
@AllArgsConstructor @Data class User { private String name; private Integer age; } @Test public void testWork3() { List<User> userList = new ArrayList<User>() {{ add(new User("jack",23)); add(new User("james",30)); add(new User("curry",28)); add(new User("tom",27)); add(new User("sue",29)); }}; List<String> collect = userList.stream() .filter(x -> x.getAge() > 27) .sorted((a, b) -> a.getAge().compareTo(b.getAge())) .limit(2) .map(User::getName) .collect(Collectors.toList()); //結(jié)果:[curry, sue] System.out.println(collect); }
4.統(tǒng)計(jì)指定集合中,姓名相同的人中年齡最小的年齡
@Test public void testWork4() { List<User> userList = new ArrayList<User>() {{ add(new User("tom", 23)); add(new User("james", 30)); add(new User("james", 28)); add(new User("tom", 27)); add(new User("sue", 29)); }}; userList.stream().collect(Collectors.groupingBy(User::getName)) .forEach((name, list) -> { User user = list.stream().sorted((a, b) -> a.getAge().compareTo(b.getAge())).findFirst().orElse(null); //結(jié)果:name:sue,age:29 // name:tom,age:23 // name:james,age:28 System.out.println("name:" + name + ",age:" + user.getAge()); }); }
總結(jié)
到此這篇關(guān)于java8 stream常用開(kāi)發(fā)技巧的文章就介紹到這了,更多相關(guān)java8 stream常用開(kāi)發(fā)技巧內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java使用gzip實(shí)現(xiàn)文件解壓縮示例
這篇文章主要介紹了java使用gzip實(shí)現(xiàn)文件解壓縮示例,需要的朋友可以參考下2014-03-03五分鐘解鎖springboot admin監(jiān)控新技巧
本文不會(huì)講如何搭建企業(yè)的運(yùn)維監(jiān)控系統(tǒng),有興趣的可以去找找成熟的比如Zabbix、Prometheus,甚至比較簡(jiǎn)單的Wgcloud都能滿足一定的需求,不在此贅述。本文講解如何使用Springboot admin對(duì)spring boot項(xiàng)目進(jìn)行應(yīng)用監(jiān)控,感興趣的朋友一起看看吧2021-06-06mybatis-plus?執(zhí)行insert(),實(shí)體的id自動(dòng)更新問(wèn)題
這篇文章主要介紹了mybatis-plus?執(zhí)行insert(),實(shí)體的id自動(dòng)更新問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12Java解決No enclosing instance of type PrintListFromTailToHead
這篇文章主要介紹了Java解決No enclosing instance of type PrintListFromTailToHead is accessible問(wèn)題的兩種方案的相關(guān)資料,需要的朋友可以參考下2016-07-07java中 spring 定時(shí)任務(wù) 實(shí)現(xiàn)代碼
java中 spring 定時(shí)任務(wù) 實(shí)現(xiàn)代碼,需要的朋友可以參考一下2013-03-03Java實(shí)現(xiàn)二分搜索樹(shù)的示例代碼
二分搜索樹(shù)是一顆二叉樹(shù),二分搜索樹(shù)每個(gè)節(jié)點(diǎn)的左子樹(shù)的值都小于該節(jié)點(diǎn)的值,每個(gè)節(jié)點(diǎn)右子樹(shù)的值都大于該節(jié)點(diǎn)的值。本文將利用Java實(shí)現(xiàn)二分搜索樹(shù),需要的可以參考一下2022-03-03java中BCryptPasswordEncoder密碼的加密與驗(yàn)證方式
這篇文章主要介紹了java中BCryptPasswordEncoder密碼的加密與驗(yàn)證方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-08-08mybatis.type-aliases-package的作用及用法說(shuō)明
這篇文章主要介紹了mybatis.type-aliases-package的作用及用法說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-01-01jackson 如何將實(shí)體轉(zhuǎn)json json字符串轉(zhuǎn)實(shí)體
這篇文章主要介紹了jackson 實(shí)現(xiàn)將實(shí)體轉(zhuǎn)json json字符串轉(zhuǎn)實(shí)體,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-10-10