程序员之家互联网科技Java 杂谈

Java集合进阶精讲!

2018-06-09  本文已影响30人  cb9841112785

集合进阶1---为集合指定初始容量

集合在Java编程中使用非常广泛,当容器的量变得非常大的时候,它的初始容量就会显得很重要了.

因为扩容是需要消耗大量的人力物力财力的。

同样的道理,Collection的初始容量也显得异常重要。所以:对于已知的情景,请为集合指定初始容量。

import java.util.ArrayList;import java.util.List;publicclassColTest{publicstaticvoidmain(String[] args){          Base_User baseUser =null;longbegin1 = System.currentTimeMillis();          List list1 =newArrayList();for(inti =0; i <1000000; i++){              baseUser =newBase_User(i,"chenssy_"+i,i);              list1.add(baseUser);          }longend1 = System.currentTimeMillis();          System.out.println("list1 time:"+ (end1 - begin1));longbegin2 = System.currentTimeMillis();          List list2 =newArrayList<>(1000000);for(inti =0; i <1000000; i++){              baseUser =newBase_User(i,"chenssy_"+i,i);              list2.add(baseUser);          }longend2 = System.currentTimeMillis();          System.out.println("list2 time:"+ (end2 - begin2));      }      }

分析:

插入1000000条数据,list1没有没有申请初始化容量,而list2初始化容量1000000。运行结果我们可以看出list2的速度是list1的两倍左右。

ArrayList的扩容机制是比较消耗资源的。我们先看ArrayList的add方法:

publicbooleanadd(E e){            ensureCapacity(size +1);            elementData[size++] = e;returntrue;        }publicvoidensureCapacity(intminCapacity){            modCount++;//修改计数器  intoldCapacity = elementData.length;//当前需要的长度超过了数组长度,进行扩容处理  if(minCapacity > oldCapacity) {                Object oldData[] = elementData;//新的容量 = 旧容量 * 1.5 + 1  intnewCapacity = (oldCapacity *3)/2+1;if(newCapacity < minCapacity)                        newCapacity = minCapacity;//数组拷贝,生成新的数组  elementData = Arrays.copyOf(elementData, newCapacity);            }        }

ArrayList每次新增一个元素,就会检测ArrayList的当前容量是否已经到达临界点,如果到达临界点则会扩容1.5倍。

然而ArrayList的扩容以及数组的拷贝生成新的数组是相当耗资源的。

大数据量的前提下,指定初始化容量,效率的提升和资源的利用会显得更加具有优势。

集合进阶2---使用entrySet遍历Map集合KV

HashMap的遍历有两种常用的方法,那就是使用keyset及entryset来进行遍历

但两者的遍历速度是有差别的。

第一种: entryset 效率高

Mapmap =newHashMap();Iteratoriter = map.entrySet().iterator();while(iter.hasNext()) {Map.Entry entry = (Map.Entry) iter.next();Objectkey = entry.getKey();Objectval = entry.getValue(); }

第二种: keySet 效率低

Mapmap =newHashMap();Iteratoriter = map.keySet().iterator();while(iter.hasNext()) {Objectkey = iter.next();Objectval = map.get(key); }

对于keySet其实是遍历了2次,一次是转为iterator,一次就从hashmap中取出key所对于的value。

而entryset只是遍历了第一次,他把key和value都放到了entry中,所以就快了。

集合进阶3---合理利用集合的稳定性和有序性

合理利用集合的稳定性(order)和有序性(sort),避免集合的无序性和不稳定性带来的负面影响。

稳定性指集合每次遍历的元素次序是一定的。

有序性是指遍历的结果按某种比较规则依次排序的。

ArrayList是order/unsort,HashMap是unorder/unsort,TreeSet是order/sort,还可以通过TreeSet结合ArrayList对结果进行排序。

Java 常用集合的一些特征:

①、LinkedList 底层是双向链表。ArrayList:底层采用数组结构,里面添加的元素有序可以重复。

②、HashSet:底层采用哈希表算法,里面添加的元素无序不可重复。

③、HashMap:底层也是采用哈希表算法,但是里面添加的元素是 key-value 的形式。key 不允许重复,value 可以。

如何好好利用这些集合的原理,简化我们的编程呢。

1、统计一字符串中每个字符出现的次数?

解析:给定一串字符串,统计每个字符出现的次数。统计的字符是不能重复的,而出现的个数我们可以不用管。那么很容易联想到 Map 的集合原理,key-value。我们将统计的字符放在 Map中是一种很好的实现方式。

HashMap

importjava.util.HashMap;importjava.util.Map;publicclassCnTest{publicstaticMap countChar(Mapmap,Stringstr){//将所给的字符串解析为一个字符构造的数组char[] chars = str.toCharArray();for(charc: chars){if(map.containsKey(c)){                    int oldCount =map.get(c);map.put(c, oldCount+1);                }else{map.put(c,1);                }            }returnmap;        }publicstaticvoid main(String[] args) {Stringstr ="hello world";//定义一个 Map 集合,用来存放统计的    字符--个数Map hashMap = newHashMap();System.out.println(countChar(hashMap,str));//{w=1, d=1,  =1, e=1, r=1, o=2, l=3, h=1}}}

补充:这里我们用来保存统计字符的是 HashMap 的实现类,这里打印出来的字符统计是无序的。

LinkedHashMap

根据字符串给定的顺序有序的统计出

publicstaticvoidmain(String[] args) {Stringstr ="hello world";//定义一个 Map 集合,用来存放统计的    字符--个数Map linkedHashMap =newLinkedHashMap();            System.out.println(countChar(linkedHashMap,str));//{h=1, e=1, l=3, o=2,  =1, w=1, r=1, d=1}}

TreeMap

用 uicode 的编码顺序打印给定的字符串

publicstaticvoidmain(String[] args) {Stringstr ="hello world";//定义一个 Map 集合,用来存放统计的    字符--个数Map treeMap =newTreeMap();            System.out.println(countChar(treeMap,str));//{ =1, d=1, e=1, h=1, l=3, o=2, r=1, w=1}}

二、去掉给定数组重复的数据?

解析:将数组中的元素都放到Set,然后将 Set 集合转变为数组就可以了。

importjava.util.HashSet;importjava.util.Set;publicclassCrTest {publicstaticInteger[] clearRepeat(int[]array){        Setset=newHashSet();for(inti :array){set.add(i);        }        Integer[] newArray =set.toArray(newInteger[set.size()]);returnnewArray;    }publicstaticvoidmain(String[] args){//创建一个数组,可以看出 2和4 是重复的int[]array= {1,2,3,4,2,2,3,4};        Integer[] newArray = clearRepeat(array);for(Integer i : newArray){            System.out.println(i);        }//1 2 3 4}}

同理我们可以改变 Set 集合的实现类,hashSet 是无序的,我们可以会用** LinkedHashSet** 保证既定顺序;TreeSet 保证自然顺序

上一篇 下一篇

猜你喜欢

热点阅读