【java总结】集合框架

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遍历linkedList
		String[] strArray2=new String[linkedList.size()];
		linkedList.toArray(strArray2);
		for(int i=0;i<strArray2.length;i++)System.out.println(strArray2[i]);
		//foreach遍历LinkedList
		for(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;
	}
	@Override
	public int compareTo(Object o) {
		// TODO Auto-generated method stub
		Num 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和value
		Iterator<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,但不能遍历key
		for (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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值