精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

Guava Collect常見的集合類

科技綠洲 ? 來源:Java技術指北 ? 作者:Java技術指北 ? 2023-10-08 11:35 ? 次閱讀

集合操作是編程中使用頻率非常高的,所有有一款針對集合的操作工具是非常有必要的。通過框架提供的工具一方面可以減少開發相似功能的耗時;同時框架在安全與穩定性上更被推薦

Guava Collect是Guava工具包中的一個子模塊,主要對jdk中的集合操作添加了一些簡易的API,同時也是對Collections工具類的擴展。當然Guava還定義了一些特定場景的數據結構以及一些針對jdk集合的優化,最典型的就是Immutable Collections(不可變集合),你會發現調用Guava API很多都是不可變的

意義

我們常見的集合類有:

  • List
  • Set
  • Vector
  • Stack
  • Map
  • Queue

集合是一種非常常見的數據結構,JDK在處理各種數據集時,提供了以上集合類型的數據結構以及其對應API方便開發者高效簡易地對數據對象操作

特色

guava主要提供了以下幾個方面的支持:

  • 增加了不可變集合
    • 不受信任的庫可以安全使用。
    • 線程安全:可以被許多線程使用,沒有競爭條件的風險。
    • 不需要支持突變,并且可以通過該假設節省時間和空間。所有不可變集合實現都比它們的可變兄弟更節省內存。(分析)
    • 可以用作常數,期望它保持不變。
  • 增加了新的集合類型
    • Multiset 與普通的Set相比,提供了元素出現頻率的記錄。可用于元素出現次數的記錄
    • Multimap 一個與Map相比,一個建可以對應對應多個值。與Spring中MultiValueMap一樣
    • BiMap 鍵值都是唯一的Map
    • Table 具有行、列的表格,數據視圖中可能更直觀。
    • ClassToInstanceMap 鍵為Class,值為Class實例的特殊Map
    • RangeSet 代表一組數據區間,類似數學中的 [1,9)
    • RangeMap 與RangeSet類似,不過將其區間作為建,可以有自己的值。[1,9) -> 'VAL'
  • 優化了常用的操作
    • 集合的創建
      ImmutableSet.of(elem ...)
      Lists.newArrayList(elem ...)
      Sets.newHashSet(elem ...)
      Maps.newHashMap()
      ...
    • 常用的操作 判斷兩個集合是否相等:Iterables.elementsEqual()
      集合分段處理:Lists.partition()
      取集合的交集:Sets.intersection()
      取集合的差集:Sets.difference()
      ...

使用

Guava Collect作為集合操作工具,我們主要從實際業務中了解其能夠幫助我們實現怎樣的需求,下面看下其API的使用情況:

假設我們有10000名學生,通過Faker生成這些模擬的學生數據數據:

List< Student > students = new ArrayList<  >();
Faker faker = new Faker(Locale.CHINA);
@Before
public void init(){
    Faker enFaker = new Faker();
    Name name = faker.name();
    IntStream.range(0,10000).forEach(index- >{
        students.add(
        Student.of()
        .setId(String.valueOf(index+1))
        .setName(name.name())
        .setAge(faker.number().numberBetween(18,22))
        .setGender(new String[]{"男","女"}[faker.number().numberBetween(0,2)])
        .setAddress(faker.address().streetAddress())
        .setScore(faker.number().randomDouble(3,50,100))
        .setEmail( faker.internet().emailAddress(enFaker.name().username()))
        .setTelephone(faker.phoneNumber().cellPhone())
        );
    });
}

Multiset
獲取元素出現頻次。比如獲取男生與女生的學生數量分別為多少

@Test
    public void multiset(){
        Multiset multiset = HashMultiset.create();
        students.forEach(student - > {
            if(Objects.equals(student.getGender(),"男")){
                multiset.add("男");
            }else{
                multiset.add("女");
            }
        });

        System.out.println("學生中男生數量:"+ multiset.count("男"));
        System.out.println("學生中女生數量:"+ multiset.count("女"));
    }

Multimap
一個鍵對應多個值時。比如查看各個年齡的學生是哪些

@Test
    public void multimap(){
        ListMultimap< Integer, Student > multimap =
                MultimapBuilder.hashKeys().arrayListValues().build();

        students.forEach(student - > {
            multimap.put(student.getAge(),student);
        });

        System.out.println( multimap.get(20) );
    }

BiMap
鍵和值都是唯一時。比如處理學生的郵箱和手機號,客戶互換鍵值位置

@Test
    public void biMap(){
        BiMap biMap = HashBiMap.create();

        students.forEach(student - > {
            biMap.put(student.getEmail(),student.getTelephone());
        });

        BiMap inverse = biMap.inverse();// 鍵值更換

        System.out.println( biMap );
        System.out.println( inverse );
    }

Table
二維表,通過行(鍵)、列(鍵)取值 比如可以以學生為行數據,其中id為行鍵,列名分別為學生屬性名稱

ID姓名年齡性別
1TOM22
@Test
    public void table(){
        Table< String, String, Object > weightedGraph = HashBasedTable.create();
        students.forEach(student - > {
            weightedGraph.put(student.getId(), "姓名", student.getName());
            weightedGraph.put(student.getId(), "年齡", student.getAge());
            weightedGraph.put(student.getId(), "性別", student.getGender());
            weightedGraph.put(student.getId(), "郵箱", student.getEmail());
            weightedGraph.put(student.getId(), "電話", student.getTelephone());
            weightedGraph.put(student.getId(), "地址", student.getAddress());
            weightedGraph.put(student.getId(), "分數", student.getScore());
        });

        Map< String, Object > row = weightedGraph.row("1");
        Map< String, Object > column = weightedGraph.column("姓名");
        Set< Table.Cell< String, String, Object >> cells = weightedGraph.cellSet();

        System.out.println( row );
        System.out.println( column );
        System.out.println( cells );
    }

ClassToInstanceMap
當值是鍵的類型實例時,通過該Map現在鍵值關系

@Test
    public void classToInstanceMap(){
        ClassToInstanceMap< Number > numberDefaults = MutableClassToInstanceMap.create();
    
        numberDefaults.put(Number.class,1);
    
        Map< Class,Object > objectMap = new HashMap<  >();
        objectMap.put(Number.class,2);
    }

RangeSet
區間Set。比如通過學生分數確定學生等級

@Test
    public void rangeSet(){
        RangeSet< Double > ArangeSet = TreeRangeSet.create();
        ArangeSet.add(Range.closed(90d,100d)); // [90,100]
        RangeSet< Double > BrangeSet = TreeRangeSet.create();
        BrangeSet.add(Range.closedOpen(80d,90d)); // [80,90)
        RangeSet< Double > CrangeSet = TreeRangeSet.create();
        CrangeSet.add(Range.closedOpen(70d,80d)); // [70,80)
        RangeSet< Double > DrangeSet = TreeRangeSet.create();
        DrangeSet.add(Range.closedOpen(60d,70d)); // [60,70)
        RangeSet< Double > ErangeSet = TreeRangeSet.create();
        ErangeSet.add(Range.lessThan(60d)); // [...,60)

        students.forEach(student - > {
            System.out.print( " 學生:"+ student.getName() );
            System.out.print( ",分數為:"+ student.getScore() );
            String rank = "";
            if(ArangeSet.contains(student.getScore())){
                rank = "A";
            }else if(BrangeSet.contains(student.getScore())){
                rank = "B";
            }else if(CrangeSet.contains(student.getScore())){
                rank = "C";
            }else if(DrangeSet.contains(student.getScore())){
                rank = "D";
            }else if(ErangeSet.contains(student.getScore())){
                rank = "E";
            }
            System.out.print( ",等級為:"+ rank +"n");
        });
    }

RangeMap和RangeSet類似,區別是添加了區間命名。和上面一樣

@Test
    public void rangeMap(){
        RangeMap< Double, String > rangeMap = TreeRangeMap.create();
        rangeMap.put(Range.closed(90d,100d),"A"); // [90,100]
        rangeMap.put(Range.closedOpen(80d,90d),"B"); // [80,90)
        rangeMap.put(Range.closedOpen(70d,80d),"C"); // [70,80)
        rangeMap.put(Range.closedOpen(60d,70d),"D"); // [60,70)
        rangeMap.put(Range.lessThan(60d),"E"); // [...,60)

        students.forEach(student - > {
            System.out.print( " 學生:"+ student.getName() );
            System.out.print( ",分數為:"+ student.getScore() );
            System.out.print( ",等級為:"+ rangeMap.get(student.getScore()) +"n");
        });
    }

下面看下對常用集合的一些操作

當然我們首先需要將數據使用Guava Collect對應的數據結構來存儲數據,這樣才能使用其對應的API:

  • 集合創建 FluentIterable.of(elem ...)
    Lists.newArrayList(elem ...)
    Sets.newHashSet(elem ...)
    Maps.newHashMap()
    HashMultiset.create()
    ArrayListMultimap.create()
    Tables.newCustomTable(Maps.newLinkedHashMap(), () -> Maps.newLinkedHashMap())
  • 條件過濾
    FluentIterable.filter(predicate); FluentIterable.anyMatch(predicate); FluentIterable.allMatch(predicate); FluentIterable.firstMatch(predicate);
  • 拆分 Iterables.partition(list, pageSize); // 拆解集合
  • 計算 Iterables.frequency(list, elem); //元素出現的次數
  • 集合的并集、交集、差集 // 并集 Sets.union(set1, set2); // 交集 Sets.intersection(set1, set2); // 差集 set1為參考 Sets.difference(set1, set2); // 并集-交集 Sets.symmetricDifference(set1, set2); // 同上 Sets.difference(Sets.union(set1, set2),Sets.intersection(set1, set2) ); // 笛卡爾積 Sets.cartesianProduct(Arrays.asList(Sets.newHashSet(1, 2, 3), Sets.newHashSet(3, 4, 5, 6)); // Map,KV相同的部分 difference.entriesInCommon(); // 同K不同V difference.entriesDiffering(); // 左邊存在的右邊不存的K difference.entriesOnlyOnLeft(); // 右邊存在的左邊不存的K difference.entriesOnlyOnRight();
  • 索引 // 將元素中的子項作為索引,由于元素檢索 Maps.uniqueIndex() Multimaps.index()

Jdk中的集合操作

自從Jdk中引入了集合Stream的操作后,從很大程度上簡化了對集合的操作,以前大量代碼現在可能簡單幾行就能夠達到相同的效果,同時支持并發處理,一并提升了效率。

下面看下常見的集合基于stream操作,同樣以上面的學生為例:

遍歷 forEach

@Test
    public void forEach(){
        students.stream().forEach(System.out::println);
    }

轉換 map
將元素轉換成其他類型。比如根據學生名稱、性別組成新的List;以id為鍵元素為值的Map或者學生姓名拼接的字符串等等

@Test
    public void transform(){
        // 轉換為數組
        List< String > listResult = students.stream()
        .map((val)- > val.getName() + ":" + val.getGender()).collect(Collectors.toList());
        System.out.println( listResult );
    
        // 轉換成String
        String stringResult = students.stream().map(Student::getName).collect(Collectors.joining());
        System.out.println( stringResult );
    
        // 轉換成Map
        Map< String, Student > mapResult = students.stream().collect(
        // key ,value ,mergerOperation, initialization
        Collectors.toMap(Student::getName,Student::self,(v1,v2)- >{
            // 出現相同key時的合并規則
            return null;
            },HashMap::new)
        );
        System.out.println( mapResult );
    }

過濾 filter
根據條件匹配滿足要求的元素。如找出分數大于80分的學生

@Test
    public void filter(){
        List< Student > filterResult = students.stream().filter((val)- >{
            return val.getScore() >80;
        }).collect(Collectors.toList());
        System.out.println(filterResult);
    }

拆解 flatMap
將二層級集合進行拆解,并成一級集合。如[[1,2,3],[4,5,6]] -> [1,2,3,4,5,6]

@Test
    public void flatMap(){
        //復合拆解
        List< Integer > result = Stream.of(Arrays.asList(1, 2, 3), Arrays.asList(4, 5, 6))
                .flatMap(subList - > subList.stream())
                .collect(Collectors.toList());
        System.out.println(result);// 1 2 3 4 5 6
    }

計算實現數據的匯總、求平均值、最大值...,當然主要針對數字(Number)類型

@Test
    public void calculate(){
        // 求和
        double sum = students.stream().mapToDouble(Student::getScore).sum();
        // 最大值
        double max = students.stream().mapToDouble(Student::getScore).max().getAsDouble();
        // 最小值
        double min = students.stream().mapToDouble(Student::getScore).min().getAsDouble();
        // 平均值
        double avg = students.stream().mapToDouble(Student::getScore).average().getAsDouble();
        // 歸約運算 fold . count、sum、min、max、average
        DoubleSummaryStatistics doubleSummaryStatistics = students.stream().mapToDouble(Student::getScore).summaryStatistics();
    }

歸納計算 reduce
在很多語言中都存在的函數,如pythonjavascript。數據的累加、map的功能

@Test
    public void reduce(){
        // 結果和identity(初始值)類型相同
        // identity accumulator combiner
        Map result = students.stream().reduce(
                new HashMap< String,Student >(), //初始值
                (map, student) - > {
                    map.put(student.getId(),student);
                    return map;
                },
                (map1, map2) - > {
                    // 并發執行時的map合并
                    return null;
                }
        );
    }

并發 parallel
上面的操作我們還可以使用parallel對stream并發處理

Arrays.asList().stream().parallel()...;
    Arrays.asList().parallelStream()...;

分段處理對集合按固定規格分段處理,處理大批量數據時,結合parallel實現分段并發處理來提示效率

@Test
    public void partition(){
        List< String > list = new ArrayList<  >();
        int partition = 100; //每段100個元素
    
        int part = list.size() / partition  + (list.size() % partition==0? 0:1);
        Stream.iterate(0, n - > n+1)
                .limit(part)
                .parallel() //并發
                .map(index - > list.stream().skip(index * partition).limit(partition).parallel().collect(Collectors.toList()))
                .forEach(System.out::println);
    }

總結

本章主要介紹了Guava Collect部分,以及對集合操作的常用API,通過示例可以看到有其對JDK集合的擴展有了更廣泛與簡易的操作。同時在JDK引入 了Stream操作后,Guava Collect中的很多功能通過Stream也可以比較容易的實現了,當然具體如何選擇根據實際情況。需要注意的是Guava Collect中 返回的基本都是不可變的集合,這樣在對數據的操作會更加的安全。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 模塊
    +關注

    關注

    7

    文章

    2674

    瀏覽量

    47350
  • 編程
    +關注

    關注

    88

    文章

    3596

    瀏覽量

    93609
  • Collector
    +關注

    關注

    0

    文章

    3

    瀏覽量

    5985
  • JDK
    JDK
    +關注

    關注

    0

    文章

    81

    瀏覽量

    16579
收藏 人收藏

    評論

    相關推薦

    java中的IO流與Guava工具

    Guava IO 日常系統交互中,文件的上傳下載都是常見的,一般我們會通過jdk提供的IO操作庫幫助我們實現。IO指的是數據相對當前操作程序的入與出,將數據通過 輸出流從程序輸出,或者通過輸入流將
    的頭像 發表于 09-25 16:24 ?703次閱讀

    java集合干貨系列

    :List列表、Set集合、Map映射、工具(Iterator迭代器、Enumeration枚舉、Arrays和Collections)。  Collection接口、子接口以及實現
    發表于 12-14 15:11

    Python 集合set添加刪除操作

    、創建集合setpython set是在python的sets模塊中,新的python版本可以直接創建集合,不需要導入sets模塊。具體用法:1. set('old')2.set(‘o’,’l’,’d
    發表于 03-05 15:29

    python入門知識:什么是set集合

    進行交并差等,既可以使用union一的英文方法名,也可以更方便的使用減號表示差集,“&”表示交集,“|”表示并集 。 集合數據類型屬于Python內置的數據類型,但不被重視,在很多書籍中甚至都看不到
    發表于 09-24 16:29

    Java 那些最常用的工具

    ());Google Guava集合的創建// 普通集合的創建List list = Lists.newArrayList();Set set = Sets.newHashSet();// 不可變
    發表于 06-15 17:18

    在Labview中使用GC.Collect

    請教各位一下,GC.Collect在Labview中使用,可以釋放掉內存么?怎樣調用GC.Collect?感謝
    發表于 06-07 08:35

    D音頻功放IC常見問答

    常見問題解答的第1部分提供了關于D放大器的概論,并回答了如何進行選擇放大器以及D放大器濾波器的設計問題。 什么是D放大器 D放大器使
    發表于 03-28 10:47 ?6955次閱讀

    JAVA集合匯總

    多數情況下使用。 二、層次關系 如圖所示:圖中,實線邊框的是實現,折線邊框的是抽象,而點線邊框的是接口 Collection 接口是集合的根接口,Java中沒有提供這個接口的直接
    的頭像 發表于 01-16 11:50 ?3764次閱讀
    JAVA<b class='flag-5'>集合</b><b class='flag-5'>類</b>匯總

    數組與集合說明

    對數組與集合進行詳細介紹。
    發表于 03-17 14:28 ?6次下載
    數組與<b class='flag-5'>集合</b><b class='flag-5'>類</b>說明

    Visual C++ 2010 CLR集合

    在實際應用中,經常需要處理集合:一些相同類型或不同類型的對象的集合。其中最常用的集合就是數組,在前面的章節中已經學習了利用System::array對數組進行操作。但是這里的數組要求
    發表于 07-14 16:24 ?0次下載

    Map集合基本元素的實現演變

    說到集合,之前介紹的ArrayList,HashMap可能是大家日常用的最多的,但是對于另一個集合
    的頭像 發表于 10-10 16:14 ?393次閱讀
    Map<b class='flag-5'>類</b><b class='flag-5'>集合</b>基本元素的實現演變

    Guava中這些Map的操作,讓我的代碼量減少了50%

    Guava是google公司開發的一款Java庫擴展工具包,內含了豐富的API,涵蓋了集合、緩存、并發、I/O等多個方面。
    的頭像 發表于 10-20 11:30 ?371次閱讀
    <b class='flag-5'>Guava</b>中這些Map的操作,讓我的代碼量減少了50%

    python怎么定義空集合

    在Python中,可以通過兩種方式來定義一個空集合: 使用大括號 {} 創建空集合 使用 set() 函數創建空集合 第一種方式是最常見的,直接使用大括號 {} 來創建一個沒有任何元素
    的頭像 發表于 11-21 16:20 ?5143次閱讀

    java的util包下有哪些

    在Java的util包下,包含了許多,用于提供各種常見的實用工具和數據結構。以下是一些常見: ArrayList:動態數組,可以根據需要自動調整大小。 LinkedList:雙向
    的頭像 發表于 11-22 15:04 ?1093次閱讀

    Java集合API的改進介紹

    簡介 本文我們將探討不同 jdk 版本中各類的起源,以及新引入的和接口背后的目的。我們將分析之前版本存在的問題,以及為何需要引入新的或接口。此外,我們還將介紹集合和接口中的新特性
    的頭像 發表于 11-22 11:12 ?107次閱讀
    Java<b class='flag-5'>集合</b>API的改進介紹