JAVA——集合框架概述

Java集合框架的基础接口

所有集合类都位于java.util包下,Java的集合类主要由两个接口派生而出:Collection和Map,Collection和Map是Java集合框架的根接口,这两个接口又包含了一些子接口或实现类。

Collection接口有两个主要的子接口List和Set,注意Map不是Collection的子接口
在这里插入图片描述

List

List接口继承于Collection接口,有序集合,可包含重复元素。可通过索引访问任何元素。List更像长度动态变换的数组。

实现类有LinkedList, ArrayList, Vector, Stack。

  • AarrayList类
    : ArrayList是一个动态数组,也是我们最常用的集合。它允许任何符合规则的元素插入甚至包括null。
    : 特点是:可随机访问,寻址容易,插入和删除困难,因此适合查询,不适合增删改。非同步。
  • LinkedList类
    : ArrayList是一个动态数组,而LinkedList是一个双向链表。它除了有ArrayList的基本操作方法外还额外提供了get,remove,insert方法在LinkedList的首部或尾部。
    : 不能随机访问,需按照双重链表执行操作,索引的操作将从开头或结尾遍历列表(从靠近指定索引的一端)。这样做的好处就是可以通过较低的代价在List中进行插入和删除操作。非同步。
  • AarrayList & LinkedList的区别

1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
2.ArrayList是由Array所支持的基于一个索引的数据结构,可对元素的随机访问。但LinkedList存储一系列的节点数据,每个节点都与前一个和下一个节点相连接。虽然有使用索引获取元素的方法,内部实现是从起始点开始遍历,遍历到索引的节点然后返回元素,比ArrayList慢。
3.与ArrayList相比,在LinkedList中插入、添加和删除一个元素会更快,因为在一个元素被插入到中间的时候,不会涉及改变数组的大小,或更新索引。
4.LinkedList比ArrayList消耗更多的内存,因为LinkedList中的每个节点存储了前后节点的引用。

  • 实现List遍历的两种方法:
       List list=new ArrayList();
		//添加数据
		list.add("nhj");
		list.add("nhdf");
		list.add("dfd");
		list.add("dfd");
		//也可指定下标进行添加
		list.add(2,"ks");
		
		//集合的单个查询(下标)    注意下标越界问题
		System.out.println(list.get(3));
		//for遍历   list.size()集合的真实长度
		for (int i = 0; i < list.size(); i++) {
			System.out.println(list.get(i));
		}
		//foreach遍历
		for (Object ob : list) {
			System.out.println(ob.toString());
		}
  • Vector类
    : 与ArrayList相似,但是Vector是同步的。所以说Vector是线程安全的动态数组。它的操作与ArrayList几乎一样。
  • Stack 类
    : Stack继承自Vector,实现一个后进先出的堆栈。Stack提供5个额外的方法使得Vector得以被当作堆栈使用。基本的push和pop 方法,还有peek方法得到栈顶的元素,empty方法测试堆栈是否为空,search方法检测一个元素在堆栈中的位置。Stack刚创建后是空栈。

Set

Set是一种不包括重复元素的Collection。它维持它自己的内部排序,所以随机访问没有任何意义。与List一样,它同样允许null的存在但是仅有一个。

虽然Set中元素没有顺序,但是元素在set中的位置是由该元素的HashCode决定的,其具体位置其实是固定的。

实现类有散列集HashSet、链式散列集LinkedHashSet和树形集TreeSet。

  • HashSet类
    : 它不允许出现重复元素
    : 不保证集合中元素的顺序
    : 允许包含值为null的元素,但最多只能有一个null元素。
    : HashSet的实现是不同步的。
  • TreeSet类
    : 该接口由 TreeMap 实例支持。此类保证排序后的 set 按照升序排列元素,根据使用的构造方法不同,可能会按照元素的自然顺序 进行排序,或按照在创建 set 时所提供的比较器进行排序。
    : TreeSet描述的是Set的一种变体——可以实现排序等功能的集合,它在将对象元素添加到集合中时会自动按照某种比较规则将其插入到有序的对象序列中.
    : 允许包含值为null的元素,但最多只能有一个null元素。
    : HashSet是基于Hash算法实现的,其性能通常优于TreeSet,我们通常都应该使用HashSet,在我们需要排序的功能时,我门才使用TreeSet。

Map接口

Map与List、Set接口不同,它是由一系列键值对组成的集合,提供了key到Value的映射。同时它也没有继承Collection。

在Map中它保证了key与value之间的一一对应关系。一个key对应一个value,所以它不能存在相同的key值,value值可以相同。

  • HashMap类

    • 以哈希表数据结构实现,查找对象时通过哈希函数计算其位置,它是为快速查询而设计的,其内部定义了一个hash表数组(Entry[] table),元素会通过哈希转换函数,将元素的哈希地址转换 成数组中存放的索引,如果有冲突,则使用散列链表的形式将所有相同哈希地址的元素串起来,可能通过查看HashMap.Entry的源码它是一个单链表结构。
    • HashMap在Map.Entry静态内部类实现中存储key-value对。在put和get方法中,它使用hashCode()和equals()方法。
    • 当传递key-value对调用put方法的时候,HashMap使用Key hashCode()和哈希算法来找出存储key-value对的索引。
    • Entry存储在LinkedList中,所以如果存在entry,它使用equals()方法来检查传递的key是否已经存在,如果存在,它会覆盖value,如果不存在,它会创建一个新的entry然后保存。
    • 当传递key调用get方法时,它再次使用hashCode()来找到数组中的索引,然后使用equals()方法找出正确的Entry,然后返回它的值。
  • Hashtable类

    • 与HashMap相似,Hashtable是同步的,HashMap非同步。
    • Hashtable继承Map接口,实现一个key-value映射的哈希表。任何非空(non-null)的对象都可作为key或者value。
    • 添加数据使用put(key, value),取出数据使用get(key),这两个基本操作的时间开销为常数。
  • LinkedHashMap类

    • LinkedHashMap是HashMap的一个子类,它保留插入的顺序,如果需要输出的顺序和输入时的相同,那么就选用LinkedHashMap。
    • LinkedHashMap是Map接口的哈希表和链接列表实现,具有可预知的迭代顺序。此实现提供所有可选的映射操作,并允许使用null值和null键。此类不保证映射的顺序,特别是它不保证该顺序恒久不变。
    • LinkedHashMap实现与HashMap的不同之处在于,后者维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,该迭代顺序可以是插入顺序或者是访问顺序。
    • 根据链表中元素的顺序可以分为:按插入顺序的链表,和按访问顺序(调用get方法)的链表。默认是按插入顺序排序,如果指定按访问顺序排序,那么调用get方法后,会将这次访问的元素移至链表尾部,不断访问可以形成按访问顺序排序的链表。
  • HashMap & Hashtable的区别

1.同步性:HashTable是线程安全的,也就是说是同步的,而HashMap是线程序不安全的,不是同步的 。
2.对null值的处理:HashMap的key、value都可为null,HashTable的key、value都不可为null 。
3.基类不同:HashMap继承于AbstractMap,而Hashtable继承于Dictionary。
4.支持的遍历种类不同:HashMap只支持Iterator(迭代器)遍历。而Hashtable支持Iterator(迭代器)和Enumeration(枚举器)两种方式遍历。
5.在Java1.4中引入了LinkedHashMap,HashMap的一个子类,如果遍历顺序,你很容易从HashMap转向LinkedHashMap,但是HashTable不是这样的,它的顺序是不可预知的。
6.HashTable被认为是个遗留的类,如果你寻求在迭代的时候修改Map,你应该使用CocurrentHashMap。

  • 实现Map遍历:
       //创建Map集合
		Map map=new HashMap();
		//添加数据
		map.put("sb", "sd");
		map.put("sb2", "sd");
		map.put("sb3", "sdsd");
		//键值重复时 会进行数据覆盖 不会报错
		map.put("sb3", "sdsd2");
		System.out.println("key\t\tvalue");
		//对所有key值遍历
		for (Object k : map.keySet()) {
			System.out.println(k.toString()+"\t\t"+map.get(k));
		}

Iterator迭代器

Iterator接口提供遍历任何Collection的接口。我们可以从一个Collection中使用迭代器方法来获取迭代器实例。迭代器取代了Java集合框架中的Enumeration。迭代器允许调用者在迭代过程中移除元素。

Enumeration的速度是Iterator的两倍,也使用更少的内存。Enumeration是非常基础的,也满足了基础的需要。但是Iterator更加安全,因为当一个集合正在被遍历的时候,它会阻止其它线程去修改集合。

迭代器取代了Java集合框架中的Enumeration。迭代器允许调用者从集合中移除元素,而Enumeration不能做到。为了使它的功能更加清晰,迭代器方法名已经经过改善。

Iterator提供的API接口如下:

  • boolean hasNext():判断集合里是否存在下一个元素。如果有,hasNext()方法返回 true。
  • Object next():返回集合里下一个元素。
  • void remove():删除集合里上一次next方法返回的元素。

注意:

  • Iterator只能单向移动。
  • Iterator.remove()是唯一安全的方式来在迭代过程中修改集合;如果在迭代过程中以任何其它的方式修改了基本集合将会产生未知的行为。而且每调用一次next()方法,remove()方法只能被调用一次,如果违反这个规则将抛出一个异常。

ListIterator

  • ListIterator是一个功能更加强大的迭代器, 它继承于Iterator接口,但只能用于各种List类型的访问。
  • 可以通过调用ListIterator()方法产生一个指向List开始处的ListIterator, 还可以调用ListIterator(n)方法创建一个一开始就指向列表索引为n的元素处的ListIterator。
  • 双向移动(向前/向后遍历)
  • 产生相对于迭代器在列表中指向的当前位置的前一个和后一个元素的索引.
    可以使用set()方法替换它访问过的最后一个元素.
    可以使用add()方法在next()方法返回的元素之前或previous()方法返回的元素之后插入一个元素.

Iterator & ListIterator的区别

1.我们可以使用Iterator来遍历Set和List集合,而ListIterator只能遍历List。
2.Iterator只可以向前遍历,而LIstIterator可以双向遍历。
3.ListIterator从Iterator接口继承,然后添加了一些额外的功能,比如添加一个元素、替换一个元素、获取前面或后面元素的索引位置。
4.ListIterator有add()方法,可以向List中添加对象,而Iterator不能
5.ListIterator可以定位当前的索引位置,nextIndex()和previousIndex()可以实现。Iterator没有此功能。
6.都可实现删除对象,但是ListIterator可以实现对象的修改,set()方法可以实现。Iierator仅能遍历,不能修改。

Iterato遍历集合:

        //获取迭代器
		Iterator it=list.iterator();
		//使用迭代器遍历List集合
		while (it.hasNext()) {
			System.out.println(it.next().toString());//it.next()返回object类型
		}
		
		//获取迭代器   需要点出key 或value
		Iterator it=map.keySet().iterator();
		//使用迭代器遍历map集合
		while (it.hasNext()) {
			//获取key
			Object key=it.next();
			System.out.println(key+"\t\t"+map.get(key));
		}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值