【java总结】集合框架

来源:互联网 发布:淘宝天天特价概念 编辑:程序博客网 时间:2024/06/05 03:21

Collection是集合框架层次结构中的根接口。Collection 表示一组对象,这些对象也称为 collection 的元素。一些 collection 允许有重复的元素,而另一些则不允许。一些 collection 是有序的,而另一些则是无序的。Collection接口下有最常用的接口为List跟Set。需要注意的是,Map并没有实现Collection接口。



List接口实现类ArrayList

优点:类似数组的形式进行存储,因此它的随机访问速度极快。
缺点:不适合于在线性表中间需要频繁进行插入和删除操作。因为每次插入和删除都需要移动数组中的元素,它是用数组存储元素的,这个数组可以动态创建,如果元素个数超过了数组的容量,那么就创建一个更大的新数组,并将当前数组中的所有元素都复制到新数组中。

public class ArrayListTest {public static void main(String[] args){List<String> arrayList=new ArrayList<String>();arrayList.add("Welcome");arrayList.add("to");arrayList.add("java");//把ArrayList变为数组相关的内容进行遍历String[] strArray=new String[arrayList.size()];arrayList.toArray(strArray);for(int i=0;i<strArray.length;i++)System.out.println(strArray[i]);//使用迭代器进行ArrayList遍历Iterator<String> iter=arrayList.iterator();while(iter.hasNext()){System.out.println(iter.next());}}}

List接口实现类LinkedList

优点:适合于在链表中间需要频繁进行插入和删除操作。
缺点: 随机访问速度较慢。查找一个元素需要从头开始一个一个的找。此类实现 Deque 接口,为 add、poll 提供先进先出队列操作,以及其他堆栈和双端队列操作LinkedList是在一个链表中存储元素。

public class LinkedListTest {public static void main(String[] args){List<String> linkedList=new LinkedList<String>();//使用ForEach遍历linkedListString[] strArray2=new String[linkedList.size()];linkedList.toArray(strArray2);for(int i=0;i<strArray2.length;i++)System.out.println(strArray2[i]);//foreach遍历LinkedListfor(String str:linkedList){System.out.println(str);}//使用迭代器进行ArrayList遍历Iterator<String> iter=linkedList.iterator();while(iter.hasNext()){System.out.println(iter.next());}}}

List接口实现类Vector:

Vector使用了关键字synchronized将访问和修改向量的方法都变成同步的了,所以对于不需要同步的应用程序来说,类ArrayList比类Vector更高效。
相同点:

①都继承于AbstractList,并且实现List接口 

②都实现了RandomAccess和Cloneable接口

③都是通过数组实现的,本质上都是动态数组,默认数组容量是10

④都支持Iterator和listIterator遍历

 不同点:

①ArrayList是非线程安全,而Vector是线程安全的

②容量增加方式不同,Vector默认增长为原来一倍,而ArrayList却是原来的一半+1

③Vector支持通过Enumeration去遍历,而List不支持


public class VectorTest {public static void main(String[] args){Vector<Integer> vector = new Vector<Integer>();for(int i = 0; i < 10; i++){            vector.add(i);        }//直接打印        System.out.println(vector.toString());        //size()        System.out.println(vector.size());        //contains        System.out.println(vector.contains(2));        //总结:对比Vector的遍历方式,使用索引的随机访问方式最快,使用迭代器最慢        //iterator遍历        Iterator<Integer> iterator = vector.iterator();        while(iterator.hasNext()){            System.out.print(iterator.next() + " ");        }        //Enumeration遍历        Enumeration enu = vector.elements();        while (enu.hasMoreElements()) {        System.out.println((Integer)enu.nextElement());        }        //toArray        Object[] objArr = vector.toArray();        System.out.println("\nobjArr:" + Arrays.asList(objArr));        Integer[] intArr = vector.toArray(new Integer[vector.size()]);        System.out.println("intArr:" + Arrays.asList(intArr));        //add        vector.add(5);        //remove        vector.remove(5);        System.out.println(vector);        //containsAll        System.out.println(vector.containsAll(Arrays.asList(5,6)));        //addAll        vector.addAll(Arrays.asList(555,666));        System.out.println(vector);        //removeAll        vector.removeAll(Arrays.asList(555,666));        System.out.println(vector);        //addAll方法        vector.addAll(5, Arrays.asList(666,666, 6));        System.out.println(vector);        //get方法        System.out.println(vector.get(5));        //set方法        vector.set(5, 55);        System.out.println(vector.get(5));        //add方法        vector.add(0, 555);        System.out.println(vector);        //remove方法        vector.remove(0);        System.out.println(vector);        //indexof方法        System.out.println(vector.indexOf(6));        //lastIndexOf方法        System.out.println(vector.lastIndexOf(6));        //listIterator方法        ListIterator<Integer> listIterator = vector.listIterator();        System.out.println(listIterator.hasPrevious());        //listIterator(index)方法        ListIterator<Integer> iListIterator = vector.listIterator(5);        System.out.println(iListIterator.previous());        //subList方法        System.out.println(vector.subList(5, 7));        //clear        vector.clear();        System.out.println(vector);    }}


List接口实现类Stack

栈类,是Java2之前引入的,继承自类Vector。同样是线程同步

public class StackTest {public static void main(String[] args){ Stack<Integer> stack = new Stack<Integer>();        for(int i = 0; i < 10; i++){            stack.add(i);        }        System.out.println(stack);        System.out.println(stack.peek());        stack.push(555);        System.out.println(stack);        System.out.println(stack.pop());        System.out.println(stack);        System.out.println(stack.empty());        System.out.println(stack.search(6));        System.out.println("stack遍历:");        while(!stack.empty()){            System.out.print(stack.pop() + " ");        }}}



List接口总结:实际使用中我们需要根据特定的需求选用合适的类,如果 除了在末尾外不能在其他位置插入或者删除元素,那么ArrayList效率更高,如果需要经常插入或者删除元素,就选择LinkedList。




Set接口实现类HashSet

HashSet是Set接口最常见的实现类,其底层是基于hash算法进行存储相关元素的。HashSet中存储元素的位置是固定的(由hashCode决定),并且是无序的。Set集合中的去重和hashCode与equals方法相关。

public class Num implements Comparable{private int num;public Num(int num){this.num=num;}@Overridepublic int compareTo(Object o) {// TODO Auto-generated method stubNum x=(Num)o;if(num>x.num)return 1;else if(num==x.num) return 0;else return -1;}public String toString(){return "num="+num;}}

public class HashSetTest {public static void main(String[] args){Set<String> hashSet=new HashSet<String>();hashSet.add("hello");hashSet.add("world");hashSet.add("world");//使用数组的方法遍历HashSet集合String[] strArray=new String[hashSet.size()];strArray=hashSet.toArray(strArray);for(String str:strArray){System.out.println(str);}//使用HashSet集合直接遍历for(String str:hashSet){System.out.println(str);}//用迭代器遍历HashSet集合Iterator<String> iterator=hashSet.iterator();while(iterator.hasNext()){System.out.println(iterator.next());}//无重写hashCode跟equals方法的类,不会自动根据类中的值进行去重Set<Num> set2=new HashSet<Num>();set2.add(new Num(1));    set2.add(new Num(3));    set2.add(new Num(2));    set2.add(new Num(3));    set2.add(new Num(3));    set2.add(new Num(6));System.out.println(set2.size());    Iterator<Num> iterator2=set2.iterator();    while(iterator2.hasNext()){        System.out.println(iterator2.next());    }}}

Set接口实现类LinkedHashSet:

LinkedHashSet继承HashSet,是用一个链表实现来扩展HashSet类,它支持对规则集内的元素排序。HashSet中的元素是没有被排序的,而LinkedHashSet中的元素可以按照它们插入规则集的顺序提取。


public class LinkedHashSetTest {public static void main(String[] args){Set<String> linkedHashSet=new LinkedHashSet<String>();linkedHashSet.add("hello");linkedHashSet.add("world");linkedHashSet.add("world");//使用数组的方法遍历HashSet集合String[] strArray=new String[linkedHashSet.size()];strArray=linkedHashSet.toArray(strArray);for(String str:strArray){System.out.println(str);}//使用HashSet集合直接遍历for(String str:linkedHashSet){System.out.println(str);}//用迭代器遍历HashSet集合Iterator<String> iterator=linkedHashSet.iterator();while(iterator.hasNext()){System.out.println(iterator.next());}}}



Set接口实现类TreeSet:

TreeSet实现了Set接口,它与HashSet的区别主要在于TreeSet中的元素会按照相关的值进行排序。HashSet是通过HashMap实现的,TreeSet是通过TreeMap实现的,只不过Set用的只是Map的key。由于TreeMap需要排序,所以需要一个Comparator为键值进行大小比较.当然也是用Comparator定位的.如果创建时没有确定,那么就会使用key.compareTo()方法,这就要求key必须实现Comparable接口.TreeMap是使用Tree数据结构实现的,所以使用compare接口就可以完成定位了.

注意:TreeSet是根据对象的CompareTo方法来去重的,如果CompaerTo返回0说明两个对象相等,不能同时存在于TreeSet中。


public class TreeSetTest {public static void main(String[] args){Set<String> treeSet=new TreeSet<String>();        treeSet.add("d");        treeSet.add("c");        treeSet.add("b");        treeSet.add("a");        //String实体类中实现Comparable接口,所以在初始化TreeSet的时候,        //无需传入比较器        Iterator<String> iterator=treeSet.iterator();       while(iterator.hasNext()){            System.out.println(iterator.next());        }        Set<Num> treeSet2=new TreeSet<Num>();        treeSet2.add(new Num(1));        treeSet2.add(new Num(3));        treeSet2.add(new Num(2));        treeSet2.add(new Num(3));        treeSet2.add(new Num(3));        treeSet2.add(new Num(6));System.out.println(treeSet2.size());        Iterator<Num> iterator2=treeSet2.iterator();        while(iterator2.hasNext())        {            System.out.println(iterator2.next());        }        TreeSet<Integer> set = new TreeSet<>();        set.add(1111);        set.add(2222);        set.add(3333);        set.add(4444);        set.add(5555);        System.out.println(set.first()); // 输出第一个元素        System.out.println(set.lower(3333)); //小于3333的最大元素        System.out.println(set.higher(2222)); //大于2222的最大元素        System.out.println(set.floor(3333)); //不大于3333的最大元素        System.out.println(set.ceiling(3333)); //不小于3333的最大元素        System.out.println(set.pollFirst()); //删除第一个元素        System.out.println(set.pollLast()); //删除最后一个元素        System.out.println(set);}}

Set接口区别于List接口在于

所有Set中的元素实现了不重复,有点像数学中集合的概念,无序,不允许有重复的元素,最多允许有一个null元素对象


Map接口:

Map接口储存一组成对的键-值对象,提供key(键)到value(值)的映射,Map中的key不要求有序,不允许重复。value同样不要求有序,但可以重复。


Map实现类HashMap

最常见的Map实现类,他的储存方式是哈希表,优点是查询指定元素效率高。HashMap采用数组+链表实现,即使用链表处理冲突,同一hash值的链表都存储在一个链表里。但是当链表中的元素较多,即hash值相等的元素较多时,通过key值依次查找的效率较低。而JDK1.8中,HashMap采用数组+链表+红黑树实现,当链表长度超过阈值(8)时,将链表转换为红黑树,这样大大减少了查找时间。 

无论什么情况HashMap中哈希表的容量总是2的n次方的一个数。并且有这样一个公式:当length=2^n时,hashcode & (length-1) == hashcode % length


HashMap与Hashtable的区别:

Hashtable实现Map接口,继承自古老的Dictionary类,实现一个key-value的键值映射表。任何非空的(key-value)均可以放入其中。 区别主要有三点:
1.Hashtable是基于陈旧的Dictionary实现的,而HashMap是基于Java1.2引进的Map接口实现的;
2.Hashtable是线程安全的,而HashMap是非线程安全的,我们可以使用外部同步的方法解决这个问题。
 3.HashMap可以允许你在列表中放一个key值为null的元素,并且可以有任意多value为null,而Hashtable不允许键或者值为null。

public class HashMapTest {public static void main(String[] args){Map<String,Integer> hashMap=new HashMap<String,Integer>();hashMap.put("a",1);hashMap.put("b",2);hashMap.put("JAVA",3);System.out.println(hashMap.get("JAVA"));//第一种遍历方法:普遍使用,二次取值for (String key : hashMap.keySet()) {    System.out.println("key= "+ key + " and value= " + hashMap.get(key));}//第二种:通过Map.entrySet使用iterator遍历key和valueIterator<Entry<String,Integer>> iter=hashMap.entrySet().iterator();while(iter.hasNext()){System.out.println(iter.next());}//第三种:通过Map.entrySet遍历key和value.推荐,尤其是容量大时for (Map.Entry<String, Integer> entry : hashMap.entrySet()) {System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());} //第四种:通过Map.values()遍历所有的value,但不能遍历keyfor (Integer v : hashMap.values()) {    System.out.println("value= " + v);}}}


Map实现类LinkedHashMap

LinkedHashMap继承自HashMap,它主要是用链表实现来扩展HashMap类,HshMap中条目是没有顺序的,但是在LinkedHashMap中元素既可以按照它们插入图的顺序排序,也可以按它们最后一次被访问 的顺序排序。LinkedHashMap继承自HashMap并且实现了Map接口。和HashMap一样,LinkedHashMap 允许key和value均为null。于该数据结构和HashMap一样使用到hash算法,因此它不能保证映射的顺序,尤其是不能保证顺序持久不变(再哈希)。


public class LinkedHashMapTest {public static void main(String[] args){Map<String,Integer> linkedHashMap=new LinkedHashMap<String,Integer>();linkedHashMap.put("a", 1);linkedHashMap.put("java",2);linkedHashMap.put("C", 3);System.out.println(linkedHashMap.get("a"));Set<Entry<String,Integer>> entry=linkedHashMap.entrySet();Iterator<Entry<String,Integer>> iter=entry.iterator();while(iter.hasNext()){System.out.println(iter.next());}Set<String> keySet=linkedHashMap.keySet();for(String x:keySet){System.out.println(x+"="+linkedHashMap.get(x));}}}


Map实现类TreeMap

TreeMap基于红黑树数据结构的实现,键值可以使用Comparable或Comparator接口来排序。TreeMap继承自AbstractMap,同时实现了接口NavigableMap,而接口NavigableMap则继承自SortedMap。SortedMap是Map的子接口,使用它可以确保图中的条目是排好序的。 TreeMap默认是根据key升序排序,同TreeSet一样,TreeMap默认是升序的key-value的key是根据Comparable实现的方法CompareTo的返回值来去重的。


public class TreeMapTest {public static void main(String[] args){Map<String,Integer> treeMap=new TreeMap<String,Integer>();treeMap.put("b",2);treeMap.put("a",1);treeMap.put("e",5);treeMap.put("d",4);treeMap.put("c",3);Set<Entry<String,Integer>> entry=treeMap.entrySet();Iterator<Entry<String,Integer>> iter=entry.iterator();while(iter.hasNext()){System.out.println(iter.next());}Set<String> keySet=treeMap.keySet();for(String x:keySet){System.out.println(x+"="+treeMap.get(x));}Map<Num,String> treeMap2=new TreeMap<Num,String>();treeMap2.put(new Num(2),"a");treeMap2.put(new Num(1),"b");treeMap2.put(new Num(5),"c");treeMap2.put(new Num(4),"d");treeMap2.put(new Num(3),"c");Set<Num> keySet2=treeMap2.keySet();//根据compareTo方法去重for(Num x:keySet2){System.out.println(x+"="+treeMap2.get(x));}//根据value排序Map<String, Integer> map = new HashMap<String, Integer>();map.put("d", 2);map.put("c", 1);map.put("b", 4);map.put("a", 3);List<Map.Entry<String, Integer>> infoIds =    new ArrayList<Map.Entry<String, Integer>>(map.entrySet());//排序前for (int i = 0; i < infoIds.size(); i++) {    String id = infoIds.get(i).toString();    System.out.println(id);}//排序Collections.sort(infoIds, new Comparator<Map.Entry<String, Integer>>() {       public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {              return (o2.getValue() - o1.getValue());         //return (o1.getKey()).toString().compareTo(o2.getKey());    }}); //排序后for (int i = 0; i < infoIds.size(); i++) {    String id = infoIds.get(i).toString();    System.out.println(id);}}}

Map接口总结:在实际使用中,如果更新图时不需要保持图中元素的顺序,就使用HashMap,如果需要保持图中元素的插入顺序或者访问顺序,就使用LinkedHashMap,如果需要使图按照键值排序,就使用TreeMap


0 0