Java中那些讓你愛(ài)不釋手工具庫(kù),精煉代碼量
一、JDK1.8 Stream新特性
1、Stream流的常見(jiàn)生成方式
①Collection體系的集合可以使用默認(rèn)方法stream()生成流
//list轉(zhuǎn)stream流 List list = new ArrayList<>(); Stream listStream = list.stream(); //Set轉(zhuǎn)stream流 Set set = new HashSet<>(); Stream setStream = set.stream(); //map轉(zhuǎn)stream流Map map = new HashMap<>(); Stream keyStream = map.keySet().stream(); Stream valueStream = map.values().stream(); Stream> entryStream = map.entrySet().stream();
②數(shù)組轉(zhuǎn)stream流
//第一種: 使用java.util.Arrays.stream(T[] array)方法用數(shù)組創(chuàng)建流 int[] array={1,3,5,6,8}; IntStream stream = Arrays.stream(array); //第二種: 可以通過(guò)Stream接口的靜態(tài)方法of(T... values)生成流 String[] strArray = {"hello", "world", "java"}; Stream strArrayStream = Stream.of(strArray); Stream strArrayStream2 = Stream.of("hello", "world", "java"); Stream intStream = Stream.of(10, 20, 30);
2、void forEach(Consumer super T> action)
Stream stringStream = Stream.of("景天", "雪見(jiàn)", "長(zhǎng)卿", "紫萱"); stringStream.forEach(System.out::println); //打印結(jié)果: ["景天", "雪見(jiàn)", "長(zhǎng)卿", "紫萱"]
3、Stream filter(Predicate predicate)
? (說(shuō)明: 用于對(duì)流中的數(shù)據(jù)進(jìn)行過(guò)濾)
List nameList = Arrays.asList("景天", "雪見(jiàn)", "長(zhǎng)卿", "紫萱");nameList.stream().filter(s -> s.startsWith("紫")).forEach(System.out::println);//打印結(jié)果: 紫萱
4、Stream map(Function super T, ? extends R> mapper)
(說(shuō)明: 可以將流中的元素映射到另一個(gè)流中)
List num = Arrays.asList(1, 2, 3, 4, 5); num.stream().map(n -> n * 2).forEach(System.out::println); //打印結(jié)果: [2, 4, 6, 8, 10]
5、Stream flatMap(Function function)
(說(shuō)明:flatmap是stream的一種中間操作,對(duì)流進(jìn)行 “扁平化” 處理,是它和stream的map一樣,是一種收集類型的stream中間操作,但是與map不同的是,它可以對(duì)stream流中單個(gè)元素再進(jìn)行拆分(切片),從另一種角度上說(shuō),使用了它,就是使用了雙重for循環(huán)。)
// map 生成的是個(gè) 1:1 映射,每個(gè)輸入元素,都按照規(guī)則轉(zhuǎn)換成為另外一個(gè)元素。還有一些場(chǎng)景,是一對(duì)多映射關(guān)系的,這時(shí)需要 flatMap String[] strs = {"java8", "is", "easy", "to", "use"}; List distinctStrs = Arrays.stream(strs) .map(str -> str.split("")) // 映射成為Stream .distinct().collect(Collectors.toList()); //distinct操作是以 “字符串?dāng)?shù)組“為單元進(jìn)行去重 /* 在執(zhí)行map操作以后,我們得到是一個(gè)包含多個(gè)字符串?dāng)?shù)組的流,打印結(jié)果如下所示 [j, a, v, a, 8] [i, s] [e, a, s, y] [t, o] [u, s, e] */ List distinctStr = Arrays.stream(strs) .map(str -> str.split("")) // 映射成為Stream .flatMap(Arrays::stream) // 扁平化為Stream .distinct().collect(Collectors.toList()); /* flatMap將由map映射得到的Stream,轉(zhuǎn)換成由各個(gè)字符串?dāng)?shù)組映射成的流Stream, 再將這些小的流扁平化成為一個(gè)由所有字符串構(gòu)成的大流Steam, 從而能夠達(dá)到我們的目的。 打印結(jié)果: [j, a, v, 8, i, s, e, y, t, o, u] */
6、Stream limit(long maxSize)
(說(shuō)明: 返回此流中的元素組成的流,截取前指定參數(shù)個(gè)數(shù)的數(shù)據(jù))
List limitList = Arrays.asList("景天", "雪見(jiàn)", "長(zhǎng)卿", "紫萱"); //取前3個(gè)數(shù)據(jù)在控制臺(tái)輸出 limitList.stream().limit(3).forEach(System.out::println); //打印結(jié)果:["景天", "雪見(jiàn)", "長(zhǎng)卿"]
7、Stream skip(long n)
(說(shuō)明: 跳過(guò)指定參數(shù)個(gè)數(shù)的數(shù)據(jù),返回由該流的剩余元素組成的流)
//跳過(guò)3個(gè)元素,把剩下的元素在控制臺(tái)輸出 List list = Arrays.asList("景天", "雪見(jiàn)", "長(zhǎng)卿", "紫萱"); list.stream().skip(3).forEach(System.out::println); //打印結(jié)果:["紫萱"]
8、static Stream concat(Stream a, Stream b)
(說(shuō)明: 合并a和b兩個(gè)流為一個(gè)流)
List concatList1 = Arrays.asList("景天", "雪見(jiàn)", "長(zhǎng)卿", "紫萱"); List concatList2 = Arrays.asList("重樓", "茂茂", "必平", "龍葵"); Stream stream1 = concatList1.stream(); Stream stream2 = concatList2.stream(); Stream.concat(stream1, stream2).forEach(System.out::println); // 打印結(jié)果: ["景天", "雪見(jiàn)", "長(zhǎng)卿", "紫萱","重樓", "茂茂", "必平", "龍葵"]
9、Stream distinct()
(說(shuō)明:對(duì)流中相同的元素進(jìn)行去重處理)
List distinctList = Arrays.asList("景天", "雪見(jiàn)", "長(zhǎng)卿", "紫萱", "紫萱", "雪見(jiàn)"); distinctList.stream().distinct().forEach(System.out::println); // 打印結(jié)果: ["景天", "雪見(jiàn)", "長(zhǎng)卿", "紫萱"]
10、Stream sorted()
(說(shuō)明:返回由此流的元素組成的流,根據(jù)自然順序排序)
//題目: 按照字母順序把數(shù)據(jù)在控制臺(tái)輸出 sorted()是正序List sortList = Arrays.asList("Lucy", "Jack", "Anny", "Vincent", "Charles","William");sortList.stream().sorted().forEach(System.out::println);//打印結(jié)果: [Anny,Charles,Jack,Lucy,Vincent,William] //題目: 按照名稱長(zhǎng)度順序從短到長(zhǎng) 把數(shù)據(jù)在控制臺(tái)輸出 sortList.stream().sorted(Comparator.comparingInt(String::length)) .forEach(System.out::println); //打印結(jié)果: [Lucy,Jack,Anny,Vincent,Charles,William]
11、Stream parallelStream()
(說(shuō)明: 并行的操作,多線程執(zhí)行,在大數(shù)據(jù)量下會(huì)優(yōu)于 stream(), parallelStream()的底層思想是ForkJoinPool主要用來(lái)使用分治法(Divide-and-Conquer Algorithm)來(lái)解決問(wèn)題)
List stringList = new ArrayList<>(); for (int i = 0; i < 10; i++) { stringList.add("第" + i + "條數(shù)據(jù)"); } long parallelStreamNowTime = System.currentTimeMillis(); stringList.parallelStream().forEach(s -> { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } }); long parallelStreamTime = System.currentTimeMillis(); System.out.println("Stream需要時(shí)間" + (parallelStreamTime - parallelStreamNowTime)); //打印結(jié)果: Stream需要時(shí)間2027
? PS:除了直接創(chuàng)建并行流,還可以通過(guò)parallel()把順序流轉(zhuǎn)換成并行流
Optional findFirst = list.stream().parallel().filter(x->x>6).findFirst();
12、count()
(說(shuō)明: 返回集合流中元素的個(gè)數(shù))
List countList = Arrays.asList("Lucy", "Jack", "Anny", "Vincent","Charles", "William","William"); long count1 = countList.stream().count();System.out.println("總元素個(gè)數(shù)是:"+count1); // 打印結(jié)果 : 總元素個(gè)數(shù)是:7 long count2 = countList.stream().distinct().count(); System.out.println("去重之后元素個(gè)數(shù)是:"+count2); // 打印結(jié)果 : 去重之后元素個(gè)數(shù)是:6
13、boolean allMatch(Predicate predicate)
(說(shuō)明:allMatch表示,判斷條件里的元素,所有的元素都滿足條件,就返回true)
List integerList = Arrays.asList(1,2,3,4,5); if(integerList.stream().allMatch(i->i>3)){ System.out.println( "值都大于3"); }
14、boolean anyMatch(Predicate predicate)
(說(shuō)明: anyMatch表示,判斷的條件里,任意一個(gè)元素符合條件,就返回true)
List integerList = Arrays.asList(1,2,3,4,5); if(integerList.stream().anyMatch(i->i>3)){ System.out.println( "存在大于3的值"); }
15、boolean noneMatch(Predicate predicate)
(說(shuō)明: noneMatch跟allMatch相反,判斷條件里的元素,所有的都不符合條件,才返回true)
List integerList = Arrays.asList(1,2,3,4,5); if(integerList.stream().noneMatch(i -> i > 3)){ System.out.println("值都小于3"); }
14、A[] toArray(IntFunction generator);
(說(shuō)明: 使用提供的 generator函數(shù)返回一個(gè)包含此流的元素的數(shù)組,以分配返回的數(shù)組,以及分區(qū)執(zhí)行或調(diào)整大小可能需要的任何其他數(shù)組。)
15、Stream concat(Stream a, b)
(說(shuō)明:合并2個(gè)stream流)
List strings = Arrays.asList("abc", "def", "gkh", "abc");//concat 合并流List strings2 = Arrays.asList("xyz", "jqx");List concatList = Stream.concat(strings2.stream(),strings.stream()) .collect(Collectors.toList());System.out.println(concatList); //打印結(jié)果: [xyz, jqx, abc, def, gkh, abc]
16、IntSummaryStatistics summaryStatistics()
(說(shuō)明: 對(duì)stream流中的數(shù)據(jù)進(jìn)行統(tǒng)計(jì)分析)
//對(duì)數(shù)組的統(tǒng)計(jì),比如用List number = Arrays.asList(1, 2, 5, 4);IntSummaryStatistics statistics = number.stream().mapToInt((x) -> x).summaryStatistics();System.out.println("列表中最大的數(shù) : "+statistics.getMax());System.out.println("列表中最小的數(shù) : "+statistics.getMin());System.out.println("平均數(shù) : "+statistics.getAverage());System.out.println("所有數(shù)之和 : "+statistics.getSum());
17、Optional findAny()
(說(shuō)明:findAny()操作,返回的元素是不確定的,對(duì)于同一個(gè)列表多次調(diào)用findAny() 有可能會(huì)返回不同的值。使用findAny()是為了更高效的性能。
①串行流情況下,一般會(huì)返回符合條件的第一個(gè)結(jié)果;
List list1 = Arrays.asList("A1", "B1", "C1", "A2", "B2", "C2", "A3", "B3","C3"); for(int i=0;i<10;i++) { Optional c = list1.stream().filter(s -> s.contains("A")).findAny(); System.out.println("====串行流findAny()======" + c.get()); } //打印結(jié)果: // ====串行流findAny()======A1 // ====串行流findAny()======A1 // ====串行流findAny()======A1 // ====串行流findAny()======A1 // ====串行流findAny()======A1 // ====串行流findAny()======A1 // ====串行流findAny()======A1 // ====串行流findAny()======A1 // ====串行流findAny()======A1 // ====串行流findAny()======A1
②并行流的情況,在給定的元素中隨機(jī)取一個(gè)元素,那就不能確保是第一個(gè)。)
List list1 = Arrays.asList("A1", "B1", "C1", "A2", "B2", "C2", "A3", "B3","C3"); Optional a = list1.parallelStream().filter(s -> s.contains("A")).findAny(); System.out.println("====findAny()======" + a.get()); //打印結(jié)果: 每次執(zhí)行打印的是A1或者A2或者A3中任意一個(gè) // ====并行流findAny()======A3// ====并行流findAny()======A3 // ====并行流findAny()======A2 // ====并行流findAny()======A1 // ====并行流findAny()======A1 // ====并行流findAny()======A2 // ====并行流findAny()======A3 // ====并行流findAny()======A3 // ====并行流findAny()======A3 // ====并行流findAny()======A2
18、Optional findFirst()
(說(shuō)明:返回Stream中的第一個(gè)元素)
List list2 = Arrays.asList("A1", "B1", "C1", "A2", "B2", "C2", "A3", "B3","C3"); Optional b = list2.parallelStream().filter(s -> s.contains("B")).findFirst(); System.out.println("====findFirst()====" + b.get());// 打印結(jié)果: ====findFirst()====B1
19、Optional max(Comparator comparator)
(說(shuō)明:返回比較器比較之后 結(jié)果最大的那個(gè)元素)
//獲取String集合中最長(zhǎng)的元素。List maxList = Arrays.asList("Lucy", "Jack", "Anny", "Vincent","Charles","William");Optional max = maxList.stream(). max(Comparator.comparing(String::length));System.out.println("最長(zhǎng)的字符串:" + max.get());//打印結(jié)果: 最長(zhǎng)的字符串:Vincent
PS: Optional
20、Optional reduce(BinaryOperator accumulator)
(說(shuō)明: 根據(jù)指定的計(jì)算模型將Stream中的值計(jì)算得到一個(gè)最終結(jié)果)
List reduceList = Arrays.asList(1, 3, 2, 8, 11, 4); // 求和方式1 Optional sum = reduceList.stream().reduce((x, y) -> x + y); // 求和方式2 Optional sum2 = reduceList.stream().reduce(Integer::sum); // 求和方式3 Integer sum3 = reduceList.stream().reduce(0, Integer::sum); // 求乘積 Optional product = reduceList.stream().reduce((x, y) -> x * y); // 求最大值方式1 Optional max2 = reduceList.stream().reduce((x, y) -> x > y ? x : y); // 求最大值寫(xiě)法2 Integer max3 = reduceList.stream().reduce(1, Integer::max); System.out.println("list求和:" + sum.get() + "," + sum2.get() + "," + sum3); //打印結(jié)果: list求和:29,29,29 System.out.println("list求積:" + product.get()); //打印結(jié)果: list求積:2112 System.out.println("list求最大值:" + max2.get() + "," + max3); //打印結(jié)果: list求最大值:11,11
二、List轉(zhuǎn)String
// 如何把list集合拼接成以逗號(hào)分隔的字符串 a,b,c List list = Arrays.asList("a", "b", "c");// 第一種方法,可以用stream流 String join = list.stream().collect(Collectors.joining(",")); System.out.println(join); // 輸出 a,b,c // 第二種方法,其實(shí)String也有join方法可以實(shí)現(xiàn)這個(gè)功能,合并數(shù)組為單一字符串,可傳分隔符 String join1 = String.join(",", list); System.out.println(join1); // 輸出 a,b,c
三、玩轉(zhuǎn)StringUtils工具類
String str = "I love JavaAlliance forever";// 1、刪除字符串中指定字符,返回一個(gè)stringString remove = StringUtils.remove(str, "forever"); // 移除字符串中的 foreverSystem.out.println(remove); // 打印結(jié)果是 I love JavaAlliance// 2、將字符串反轉(zhuǎn),返回一個(gè)stringString reverse = StringUtils.reverse(str);System.out.println(reverse); // 打印結(jié)果是 reverof ecnaillAavaJ evol I// 3、比較兩個(gè)字符串是否相等,如果兩個(gè)均為null,則也認(rèn)為相等StringUtils.equals("Java", "Java"); // 結(jié)果是trueStringUtils.equals("", ""); // 結(jié)果是trueStringUtils.equals(null, null); // 結(jié)果是trueStringUtils.equals(null, ""); // 結(jié)果是falseStringUtils.equals("", null); // 結(jié)果是falseStringUtils.equals(null, ""); // 結(jié)果是falseStringUtils.equalsIgnoreCase("java", "JAVA"); // 不區(qū)分大小寫(xiě)--結(jié)果是true// 4、重復(fù)拼接字符串String str1 = StringUtils.repeat("ab", 2);System.out.println(str1); // 輸出abab// 5、首字母轉(zhuǎn)成大寫(xiě)String str2 = "javaAlliance";String capitalize = StringUtils.capitalize(str2);System.out.println(capitalize); // 輸出JavaAlliance// 6、字符串固定長(zhǎng)度填充StringUtils.leftPad("test", 8, "0"); // 字符串固定長(zhǎng)度 8位,若不足,往左補(bǔ) 0StringUtils.rightPad("test", 8, "0"); // 字符串固定長(zhǎng)度 8位,若不足,往右補(bǔ) 0// 7、字符串關(guān)鍵字替換StringUtils.replace("aba", "a", "z") = "zbz"; // 默認(rèn)替換所有關(guān)鍵字StringUtils.replaceOnce("aba", "a", "z") = "zba";// 替換關(guān)鍵字,僅替換一次StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "") = "ABC123"; // 使用正則表達(dá)式替換// 8、將數(shù)組拼接成字符串StringUtils.join(["a", "b", "c"], ",") ; //拼接結(jié)果是 "a,b,c"http:// 9、字符串拆分StringUtils.split("a..b.c", .) //拆分結(jié)果是 ["a", "b", "c"]StringUtils.splitByWholeSeparatorPreserveAllTokens("a..b.c", ".") //拆分結(jié)果是 ["a","", "b", "c"]
四、玩轉(zhuǎn)BeanUtils工具類
User user = new User();user.setUserName("JavaAlliance").setEmail("196432@qq.com");// 對(duì)象轉(zhuǎn)mapMap map = BeanUtils.describe(user);System.out.println(map); // 輸出// map轉(zhuǎn)對(duì)象User newUser = new User();BeanUtils.populate(newUser, map);System.out.println(newUser); // 輸出
五、玩轉(zhuǎn)DateUtils/DateFormatUtils工具類
// Date類型轉(zhuǎn)String類型String date = DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss");System.out.println(date); // 輸出 2021-05-01 01:01:01// String類型轉(zhuǎn)Date類型 該方法會(huì)將日期字符串按照第二參數(shù)中的String數(shù)組,依次比對(duì),選擇合適的Pattern來(lái)解析。Date date1 = DateUtils.parseDate("2021-05-01 01:01:01", new String[]{"yyyy-MM-dd HH:mm:ss"});Date now = new Date();// Date 加 1 天Date addDays = DateUtils.addDays(now, 1);// Date 加 33 分鐘Date addMinutes = DateUtils.addMinutes(now, 33);// Date 減去 233 秒Date addSeconds = DateUtils.addSeconds(now, -233);// 判斷是否 Wie 同一天boolean sameDay = DateUtils.isSameDay(addDays, addMinutes);// 過(guò)濾時(shí)分秒,若 now 為 2020-05-07 22:13:00 調(diào)用 truncate 方法以后// 返回時(shí)間為 2020-05-07 00:00:00Date truncate = DateUtils.truncate(now, Calendar.DATE);
六、玩轉(zhuǎn)LocalDateTime工具類
Date now = new Date();// Date轉(zhuǎn)成LocalDateTime 這里指定使用當(dāng)前系統(tǒng)默認(rèn)時(shí)區(qū)LocalDateTime localDateTime = now.toInstant().atZone(ZoneId.systemDefault()) .toLocalDateTime();// LocalDateTime轉(zhuǎn)成Date 這里指定使用當(dāng)前系統(tǒng)默認(rèn)時(shí)區(qū)Date date = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());// 按照 yyyy-MM-dd HH:mm:ss 轉(zhuǎn)化時(shí)間LocalDateTime dateTime = LocalDateTime.parse("2020-05-07 22:34:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));// 將 LocalDateTime 格式化字符串String format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(dateTime);//LocalDateTime 獲取當(dāng)前時(shí)間年份,月份LocalDateTime now = LocalDateTime.now();// 年int year = now.getYear();// 月int month = now.getMonthValue();// 日int day = now.getDayOfMonth();// LocalDateTime 進(jìn)行日期加減,獲取下一天的時(shí)間LocalDateTime now = LocalDateTime.now();// 當(dāng)前時(shí)間加一天LocalDateTime plusDays = now.plusDays(1l);// 當(dāng)前時(shí)間減一個(gè)小時(shí)LocalDateTime minusHours = now.minusHours(1l);// 還有很多其他方法
七、玩轉(zhuǎn)CollectionUtils工具類
String[] arrayA = new String[]{"1", "2", "3", "4"};String[] arrayB = new String[]{"3", "4", "5", "6"};List listA = Arrays.asList(arrayA);List listB = Arrays.asList(arrayB);// 1、并集 unionSystem.out.println(CollectionUtils.union(listA, listB));// 輸出: [1, 2, 3, 4, 5, 6]// 2、交集 intersectionSystem.out.println(CollectionUtils.intersection(listA, listB));// 輸出:[3, 4]// 3、交集的補(bǔ)集(析取)disjunctionSystem.out.println(CollectionUtils.disjunction(listA, listB));// 輸出:[1, 2, 5, 6]// 4、差集(扣除)System.out.println(CollectionUtils.subtract(listA, listB));// 輸出:[1, 2] // 1、交集 List intersectionList = new ArrayList<>(listA); intersectionList.retainAll(listB); System.out.println(intersectionList); // 輸出:[3, 4] // 2、差集 List differenceList = new ArrayList<>(listA); differenceList.removeAll(listB); System.out.println(differenceList); // 輸出:[1, 2]// 3、并集 (先做差集再做添加所有)List unionList = new ArrayList<>(listA);unionList.removeAll(listB); // unionList [1, 2]unionList.addAll(listB); // 添加[3,4,5,6]System.out.println(unionList);// 輸出:[1, 2, 3, 4, 5, 6]
注意 : 以上有2種取交集的方式即intersection和retainAll,我們這里說(shuō)下它們之間的差別 ,要注意的是它們的返回類型是不一樣的,intersection返回的是一個(gè)新的List集合,而retainAll返回是Bollean類型那就說(shuō)明retainAll方法是對(duì)原有集合進(jìn)行處理再返回原有集合,會(huì)改變?cè)屑现械膬?nèi)容。
思路點(diǎn)撥:
1、從性能角度來(lái)考慮的話,List自帶會(huì)高點(diǎn),因?yàn)樗挥迷賱?chuàng)建新的集合。
2、需要注意的是:因?yàn)閞etainAll因?yàn)闀?huì)改變?cè)屑?所以該集合需要多次使用就不適合用retainAll。
注意: Arrays.asList將數(shù)組轉(zhuǎn)集合不能進(jìn)行add和remove操作。因?yàn)檎{(diào)用Arrays.asList()生產(chǎn)的List的add、remove方法時(shí)報(bào)異常,這是由Arrays.asList() 返回的市Arrays的內(nèi)部類ArrayList, 而不是java.util.ArrayList。Arrays的內(nèi)部類ArrayList和java.util.ArrayList都是繼承AbstractList,remove、add等方法AbstractList中是默認(rèn)throw UnsupportedOperationException而且不作任何操作。java.util.ArrayList重新了這些方法而Arrays的內(nèi)部類ArrayList沒(méi)有重新,所以會(huì)拋出異常。
八、玩轉(zhuǎn) Guava工具包
1、Multiset
Multiset是什么?顧名思義,Multiset和Set的區(qū)別就是可以保存多個(gè)相同的對(duì)象。在JDK中,List和Set有一個(gè)基本的區(qū)別,就是List可以包含多個(gè)相同對(duì)象,且是有順序的,而Set不能有重復(fù),且不保證順序(有些實(shí)現(xiàn)有順序,例如LinkedHashSet和SortedSet等)所以Multiset占據(jù)了List和Set之間的一個(gè)灰色地帶:允許重復(fù),但是不保證順序。
常見(jiàn)使用場(chǎng)景:Multiset有一個(gè)有用的功能,就是跟蹤每種對(duì)象的數(shù)量,所以你可以用來(lái)進(jìn)行數(shù)字統(tǒng)計(jì)。 常見(jiàn)的普通實(shí)現(xiàn)方式如下:
String str = "張三 李四 李四 王五 王五 王五"; String[] strArr = str.split(" "); List words = new ArrayList<>(Arrays.asList(strArr));//創(chuàng)建一個(gè)HashMultiset集合,并將words集合數(shù)據(jù)放入 Multiset wordMultiset = HashMultiset.create(); wordMultiset.addAll(words);//將不同的元素放在一個(gè)集合set中 for (String key : wordMultiset.elementSet()) { //查看指定元素的個(gè)數(shù) System.out.println(key + "-->" + wordMultiset.count(key)); //打印結(jié)果: 李四-->2 張三-->1 王五-->3 }
2、Multimap
Multimap能夠?qū)崿F(xiàn)一個(gè)鍵對(duì)應(yīng)到多個(gè)值的效果
Multimap myMultimap = ArrayListMultimap.create();myMultimap.put("Fruits", "Bannana");myMultimap.put("Fruits", "Apple");myMultimap.put("Fruits", "Pear");myMultimap.put("Fruits", "Pear");myMultimap.put("Vegetables", "Carrot");// 查詢Multimap中的存儲(chǔ)的元素個(gè)數(shù)System.out.println(myMultimap.size()); // 打印結(jié)果: 5//查詢鍵為“Fruits”所對(duì)應(yīng)的valueCollection fruits = myMultimap.get("Fruits");System.out.println(fruits);//打印結(jié)果: [Bannana, Apple, Pear, Pear]Collection vegetables = myMultimap.get("Vegetables");System.out.println(vegetables); //打印結(jié)果: [Carrot]// 循環(huán)迭代遍歷整個(gè) Multimap里存儲(chǔ)的value值for (String value : myMultimap.values()) { System.out.println(value); //打印結(jié)果: //Carrot //Bannana //Apple //Pear //Pear }//移除其中一個(gè)元素myMultimap.remove("Fruits", "Pear");System.out.println(myMultimap.get("Fruits"));//打印結(jié)果: [Bannana, Apple, Pear]//將鍵為"Fruits"所對(duì)應(yīng)的value內(nèi)容替換為集合 Arrays.asList("178","910","123")//返回的oldValues是之前的舊值Collection oldValues = myMultimap.replaceValues("Fruits", Arrays.asList("178","910","123"));System.out.println("oldValues="+oldValues);//打印結(jié)果: oldValues=[Bannana, Apple, Pear]System.out.println("myMultimap="+myMultimap);//打印結(jié)果: myMultimap={Vegetables=[Carrot], Fruits=[178, 910,123]}//移除Multimap中鍵為“Fruits”的所有元素myMultimap.removeAll("Fruits");System.out.println(myMultimap.get("Fruits"));//打印結(jié)果: []
3、BiMap
BiMap
可以用來(lái)實(shí)現(xiàn)鍵值對(duì)的雙向映射需求,這樣我們就可以通過(guò) Key
查找對(duì)對(duì)應(yīng)的 Value
,也可以使用 Value
查找對(duì)應(yīng)的 Key
。 Bimap要求key和value都唯一,如果key不唯一則覆蓋key,如果value不唯一則直接報(bào)錯(cuò)
//雙向mapBiMap biMap=HashBiMap.create();biMap.put(1,"張三");biMap.put(2,"李四");biMap.put(3,"王五");biMap.put(4,"趙六");biMap.put(5,"李七");biMap.put(4,"小小");//通過(guò)key值得到value值(注意key里面的類型根據(jù)泛行String value= biMap.get(1);System.out.println("id為1的value值 --"+value); //打印結(jié)果: id為1的value值 --張三//通過(guò)value值得到key值int key= biMap.inverse().get("張三");System.out.println("value為張三的key值 --"+key); //打印結(jié)果: value為張三的key值 --1//通過(guò)key值重復(fù),那么vakue值會(huì)被覆蓋。String valuename= biMap.get(4);System.out.println("id為4的value值 --"+valuename);//打印結(jié)果: id為4的value值 --小小
BiMap的常用實(shí)現(xiàn)有:
? 1、HashBiMap: key 集合與 value 集合都有 HashMap 實(shí)現(xiàn)
? 2、EnumBiMap: key 與 value 都必須是 enum 類型
? 3、ImmutableBiMap: 不可修改的 BiMap
九、玩轉(zhuǎn)FileUtils-文件操作工具類
文件操作工具類提供一系列方法,可以讓我們快速讀取寫(xiě)入文件。
快速實(shí)現(xiàn)文件/文件夾拷貝操作 ,FileUtils.copyDirectory/FileUtils.copyFile
1、獲取指定文件夾上所有文件
// 按照指定文件后綴如java,txt等去查找指定文件夾下的文件File directory = new File("E://test");FileUtils.listFiles(directory, new String[]{"txt"}, false);
2、讀取該文件所有行
// 讀取指定文件所有行 不需要使用 while 循環(huán)讀取流了List lines = FileUtils.readLines(fileA)
3、寫(xiě)文件
// 1、 向一個(gè)文件寫(xiě)入一段文字FileUtils.write(new File("D:/a/1.txt"), "文件內(nèi)容", "UTF-8", true);// 2、以追加的方式寫(xiě)入FileUtils.writeStringToFile(new File("D:/a/1.txt"), "author:apple", "UTF-8", true);//3、寫(xiě)入多行List list= new ArrayList();list.add("第一行");list.add("第二行");FileUtils.writeLines(new File("D:/a/1.txt"), list, true);
4、讀文件
//讀文件 System.out.println(FileUtils.readFileToString(new File("D:/a/1.txt"), "UTF-8"));//返回一個(gè)list System.out.println(FileUtils.readLines(new File("D:/a/1.txt"), "UTF-8"));
5、刪除文件/文件夾
// 刪除文件夾 FileUtils.deleteDirectory(new File("D:/a")); // 文件夾不是空仍然可以被刪除,永遠(yuǎn)不會(huì)拋出異常 FileUtils.deleteQuietly(new File("D:/a"));
6、復(fù)制文件
//結(jié)果是a和a1在同一目錄 FileUtils.copyDirectory(new File("D:/a"), new File("D:/a1")); //結(jié)果是將a拷貝到a2下 FileUtils.copyDirectoryToDirectory(new File("D:/a"), new File("D:/a2")); //拷貝文件 方式1 FileUtils.copyFile(new File("d:/1.xml"), new File("d:/1.xml.bak")); //拷貝文件 方式2Writer write = new FileWriter("D:/abc_bak.txt");InputStream ins = new FileInputStream(new File("D:/abc.txt"));IOUtils.copy(ins, write);write.close();IOUtils.closeQuietly(ins);//拷貝文件到目錄中 FileUtils.copyFileToDirectory(new File("d:/1.xml"), new File("d:/a")); //拷貝url到文件 FileUtils.copyURLToFile(new URL("http://www.a.com/1.xml"), new File("d:/1.xml"));//可實(shí)現(xiàn)快速下載URL url = new URL("http://hzf-image-test.oss-cn-beijing.aliyuncs.com/hr_image/HF306268301810/1513632067664AbIB40pv_defalut.JPG?x-oss-process=image/resize,h_400");File file = new File("/Users/jjs/Desktop/pic.jpg");FileUtils.copyURLToFile(url, file);
7、移動(dòng)文件
//移動(dòng)文件 或 文件夾 //static void moveDirectory(File srcDir, File destDir) FileUtils.moveDirectory(new File("D:/a1"), new File("D:/a2")); //注意這里 第二個(gè)參數(shù)文件不存在會(huì)引發(fā)異常 //static void moveDirectoryToDirectory(File src, File destDir, boolean createDestDir) FileUtils.moveDirectoryToDirectory(new File("D:/a2"), new File("D:/a3"), true); /* 上面兩個(gè)方法的不同是: * moveDirectory:D:/a2里的內(nèi)容是D:/a1的內(nèi)容。 * moveDirectoryToDirectory:D:/a2文件夾移動(dòng)到到D:/a3里 */
8、實(shí)現(xiàn)快速下載文件
//下載方式1URL url = new URL("http://www.baidu.com/img/baidu_logo.gif");File file = new File("/Users/jjs/Desktop/baidu1.gif");FileUtils.copyURLToFile(url, file);//下載方式2InputStream in = new URL("http://www.baidu.com/img/baidu_logo.gif").openStream();byte[] gif = IOUtils.toByteArray(in);FileUtils.writeByteArrayToFile(new File("D:/baidu2.gif"), gif);IOUtils.closeQuietly(in);//下載方式3InputStream in3 = new URL("http://www.baidu.com/img/baidu_logo.gif").openStream();byte[] gif3 = IOUtils.toByteArray(in3);IOUtils.write(gif3, new FileOutputStream(new File("D:/baidu3.gif")));IOUtils.closeQuietly(in3);
專注Java技術(shù)進(jìn)階,系統(tǒng)設(shè)計(jì),計(jì)算機(jī)網(wǎng)絡(luò),數(shù)據(jù)結(jié)構(gòu)算法,操作系統(tǒng),設(shè)計(jì)模式,計(jì)算機(jī)組成原理等等更多精彩內(nèi)容,盡情期待