日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
千萬不要再這樣創(chuàng)建集合了!極容易內(nèi)存泄露!

由于Java語言的集合框架中(collections, 如list, map, set等)沒有提供任何簡便的語法結(jié)構(gòu),這使得在建立常量集合時的工作非常繁索。每次建立時我們都要做:

1、定義一個空的集合類變量

2、向這個結(jié)合類中逐一添加元素

3、將集合做為參數(shù)傳遞給方法

例如,要將一個Set變量傳給一個方法:

 
 
  1. Set users = new HashSet();
  2. users.add("Hollis");
  3. users.add("hollis");
  4. users.add("HollisChuang");
  5. users.add("hollis666");
  6. transferUsers(users);

這樣的寫法稍微有些復(fù)雜,有沒有簡潔的方式呢?

雙括號語法初始化集合

其實(shí)有一個比較簡潔的方式,那就是雙括號語法(double-brace syntax)建立并初始化一個新的集合:

 
 
  1. public class DoubleBraceTest {
  2.      public static void main(String[] args) {
  3.          Set users = new HashSet() {{
  4.              add("Hollis");
  5.              add("hollis");
  6.              add("HollisChuang");
  7.              add("hollis666");
  8.          }};
  9.      }
  10.  }

同理,創(chuàng)建并初始化一個HashMap的語法如下:

 
 
  1. Map users = new HashMap<>() {{
  2.     put("Hollis","Hollis");
  3.     put("hollis","hollis");
  4.     put("HollisChuang","HollisChuang");
  5. }};

不只是Set、Map,jdk中的集合類都可以用這種方式創(chuàng)建并初始化。

當(dāng)我們使用這種雙括號語法初始化集合類的時候,在對Java文件進(jìn)行編譯時,可以發(fā)現(xiàn)一個奇怪的現(xiàn)象,使用javac對DoubleBraceTest進(jìn)行編譯:

 
 
  1. javac DoubleBraceTest.java

我們會發(fā)現(xiàn),得到兩個class文件:

 
 
  1. DoubleBraceTest.class
  2. DoubleBraceTest$1.class

有經(jīng)驗(yàn)的朋友可能一看到這兩個文件就會知道,這里面一定用到了匿名內(nèi)部類。

沒錯,使用這個雙括號初始化的效果是創(chuàng)建匿名內(nèi)部類。創(chuàng)建的類有一個隱式的this指針指向外部類。

不建議使用這種形式

首先,使用這種形式創(chuàng)建并初始化集合會導(dǎo)致很多內(nèi)部類被創(chuàng)建。因?yàn)槊看问褂秒p大括號初始化時,都會生成一個新類。如這個例子:

 
 
  1. Map hollis = new HashMap(){{
  2.     put("firstName", "Hollis");
  3.     put("lastName", "Chuang");
  4.     put("contacts", new HashMap(){{
  5.         put("0", new HashMap(){{
  6.             put("blogs", "http://www.hollischuang.com");
  7.         }});
  8.         put("1", new HashMap(){{
  9.             put("wechat", "hollischuang");
  10.         }});
  11.     }});
  12. }};

這會使得很多內(nèi)部類被創(chuàng)建出來:

 
 
  1. DoubleBraceTest$1$1$1.class
  2.  DoubleBraceTest$1$1$2.class
  3.  DoubleBraceTest$1$1.class
  4.  DoubleBraceTest$1.class
  5.  DoubleBraceTest.class

這些內(nèi)部類被創(chuàng)建出來,是需要被類加載器加載的,這就帶來了一些額外的開銷。

如果您使用上面的代碼在一個方法中創(chuàng)建并初始化一個map,并從方法返回該map,那么該方法的調(diào)用者可能會毫不知情地持有一個無法進(jìn)行垃圾收集的資源。

 
 
  1. public Map getMap() {
  2.      Map hollis = new HashMap(){{
  3.          put("firstName", "Hollis");
  4.          put("lastName", "Chuang");
  5.          put("contacts", new HashMap(){{
  6.              put("0", new HashMap(){{
  7.                  put("blogs", "http://www.hollischuang.com");
  8.              }});
  9.              put("1", new HashMap(){{
  10.                  put("wechat", "hollischuang");
  11.              }});
  12.          }});
  13.      }};
  14.      return hollis;
  15.  }

我們嘗試通過調(diào)用getMap得到這樣一個通過雙括號初始化出來的map

 
 
  1. public class DoubleBraceTest {
  2.       public static void main(String[] args) {
  3.           DoubleBraceTest doubleBraceTest = new DoubleBraceTest();
  4.           Map map = doubleBraceTest.getMap();
  5.       }
  6.   }

返回的Map現(xiàn)在將包含一個對DoubleBraceTest的實(shí)例的引用。讀者可以嘗試這通過debug或者以下方式確認(rèn)這一事實(shí)。

 
 
  1. Field field = map.getClass().getDeclaredField("this$0");
  2. field.setAccessible(true);
  3. System.out.println(field.get(map).getClass());

替代方案

很多人使用雙括號初始化集合,主要是因?yàn)樗容^方便,可以在定義集合的同時對他進(jìn)行初始化。

但其實(shí),目前已經(jīng)有很多方案可以做這個事情了,不需要再使用這種存在風(fēng)險(xiǎn)的方案。

使用Arrays工具類

當(dāng)我們想要初始化一個List的時候,可以借助Arrays類,Arrays中提供了asList可以把一個數(shù)組轉(zhuǎn)換成List:

 
 
  1. List list2 = Arrays.asList("hollis ", "Hollis", "HollisChuang");

但是需要注意的是,asList 得到的只是一個 Arrays 的內(nèi)部類,是一個原來數(shù)組的視圖 List,因此如果對它進(jìn)行增刪操作會報(bào)錯。

使用Stream

Stream是Java中提供的新特性,他可以對傳入流內(nèi)部的元素進(jìn)行篩選、排序、聚合等中間操作(intermediate operate),最后由最終操作(terminal operation)得到前面處理的結(jié)果。

我們可以借助Stream來初始化集合:java

 
 
  1. List list1 = Stream.of("hollis", "Hollis", "HollisChuang").collect(Collectors.toList());

使用第三方工具類

很多第三方的集合工具類可以實(shí)現(xiàn)這個功能,如Guava等:

 
 
  1. ImmutableMap.of("k1", "v1", "k2", "v2");
  2. ImmutableList.of("a", "b", "c", "d");

關(guān)于Guava和其中定義的不可變集合,我們在第19章節(jié)中會詳細(xì)介紹

Java 9內(nèi)置方法

其實(shí)在Java 9 中,在List、Map等集合類中已經(jīng)內(nèi)置了初始化的方法,如List中包含了12個重載的of方法,就是來做這個事情的:

 
 
  1. /**
  2.   * Returns an unmodifiable list containing zero elements.
  3.   *
  4.   * See Unmodifiable Lists for details.
  5.   *
  6.   * @param  the {@code List}'s element type
  7.   * @return an empty {@code List}
  8.   *
  9.   * @since 9
  10.   */
  11.  static  List of() {
  12.      return ImmutableCollections.emptyList();
  13.  }
  14.  static  List of(E e1) {
  15.      return new ImmutableCollections.List12<>(e1);
  16.  }
  17.  static  List of(E... elements) {
  18.      switch (elements.length) { // implicit null check of elements
  19.          case 0:
  20.              return ImmutableCollections.emptyList();
  21.          case 1:
  22.              return new ImmutableCollections.List12<>(elements[0]);
  23.          case 2:
  24.              return new ImmutableCollections.List12<>(elements[0], elements[1]);
  25.          default:
  26.              return new ImmutableCollections.ListN<>(elements);
  27.      }
  28.  }

分享題目:千萬不要再這樣創(chuàng)建集合了!極容易內(nèi)存泄露!
瀏覽路徑:http://www.dlmjj.cn/article/djppgpc.html