Java集合框架
集合框架被设计成要满足以下几个目标
- 该框架必须时高性能的,基本集合(动态数组,链表,树,哈希表)的实现也必须时高效的
- 该框架允许不同类型的集合,以类似的方式工作,具有高度的互操作性
- 对一个集合的扩展和适应必须时简单的
为此,整个集合框架就围绕一组标准接口而设计。你可以直接使用这些接口的标准实现的,诸如:LinkedList,HashSet和TreeSet等,除此之外你也可以通过这些接口实现自己的集合
从上面的集合框架图可以看到,Java集合框架主要包括两种类型的容器,一种是集合(Collection),存储一个元素集合,另一中是图(Map),存储键/值对映射;Collecation接口又有3种子类型,List、Set和Queue,再下面是一些抽象类,最后是具体实现类,常用的有ArrayList、LinkedList、HashSet、LinkHashSet、HashMap、LinkedHashMap等等
集合框架是一个用来代表和操纵集合的统一架构,所有的集合框架都包含如下内容:
- 接口:是代表集合的抽象数据类型,例如 Collection、List、Set、Map等。之所以定义多个接口,是为了以不同的方式操作集合对象
- 实现(类):是集合接口的具体实现,从本质上讲,它们是可重复使用的数据结构,例如:ArrayList、LinkedList、HashSet、HashMap
- 算法:是实现集合接口的对象里的方法执行的一些有用的计算,例如:搜索和排序,这些算法被称为多态,那是因为相同的方法可以再相似的接口上有着不同的实现
除了集合,该框架也定义了几个Map接口和类,Map里存储的是键/值对;尽管Map不是集合,但是它们完全整合再集合中
集合框架体系如图所示

Java集合框架提供了一套性能优良,使用方便的接口和类,java集合框架位于java.util包中,所以当使用集合框架的时候需要进行导包
集合接口
Set和List的区别
- Set接口实例存储的是无序的,不重复的数据;List接口实例存储的是有序的,可以重复的元素
- Set检索效率低下,删除和插入效率高,插入和删除不会引起元素位置改变<实现类有HashSet,TreeSet>
- List和数组类似,可以动态增长,根据实际存储的数据的长度自动增长List的长度;查找元素效率高,插入删除效率低,因为会引起其他元素改变<实现类有ArrayList,LinkedList,Vector>
集合实现类
Java提供了一套实现了Collerction接口的标准集合类,其中一些是具体类,这些类可以直接拿来使用,而另外一些是抽象类,提供了接口的部分实现
标准集合类汇总于下表:

在前面的教程中已经讨论通过java.util包中定义的类,如下所示:
集合算法
集合框架定义了几种算法,可用于集合和映射;这些算法被定义为集合类的静态方法。
在尝试比较不兼容的类型时,一些方法能够抛出ClassCastException异常;当试图修改一个不可修改的集合时,抛出UnsupportedOperationException异常
集合定义三个静态的变量:EMPTY_SET,EMPTY_LIST,EMPTY_MAP的;这些变量都不可改变
如何使用迭代器
通常情况下,你会希望遍历一个集合中的元素;例如,显示集合中的每个元素
一般遍历数组都是采用for循环或者增强for,这两个方法也可以用在集合框架,但时还有一种方法时采用迭代器遍历集合框架,它是一个对象,实现了 lterator接口或Listlterator接口
迭代器,使你能够通过循环来得到或删除集合的元素;Listlterator继承了lterator,以允许双向遍历列表和修改元素\
遍历ArrayList
```java import java.util.*;
public class Test{
public static void main(String[] args) {
List
//第二种遍历,把链表变为数组相关的内容进行遍历String[] strArray=new String[list.size()];list.toArray(strArray);for(int i=0;i<strArray.length;i++) //这里也可以改写为 for(String str:strArray) 这种形式{System.out.println(strArray[i]);}//第三种遍历 使用迭代器进行相关遍历Iterator<String> ite=list.iterator();while(ite.hasNext())//判断下一个元素之后有值{System.out.println(ite.next());}
} }
<a name="zFWvZ"></a>### 解析三种方法都是用来遍历ArrayList集合,第三种方法是采用迭代器的方法,该方法可以不用担心在遍历的过程中会超出集合的长度<a name="qCXIs"></a>## 遍历Map```javaimport java.util.*;public class Test{public static void main(String[] args) {Map<String, String> map = new HashMap<String, String>();map.put("1", "value1");map.put("2", "value2");map.put("3", "value3");//第一种:普遍使用,二次取值System.out.println("通过Map.keySet遍历key和value:");for (String key : map.keySet()) {System.out.println("key= "+ key + " and value= " + map.get(key));}//第二种System.out.println("通过Map.entrySet使用iterator遍历key和value:");Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();while (it.hasNext()) {Map.Entry<String, String> entry = it.next();System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());}//第三种:推荐,尤其是容量大时System.out.println("通过Map.entrySet遍历key和value");for (Map.Entry<String, String> entry : map.entrySet()) {System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());}//第四种System.out.println("通过Map.values()遍历所有的value,但不能遍历key");for (String v : map.values()) {System.out.println("value= " + v);}}}
如何使用比较器
TreeSet和TreeMap的按照排序顺序来存储元素,然而,这是通过比较器来精确定义按照什么样的排序顺序
这个接口可以让我们以不同的方式来排序一个集合
总结
Java集合框架为程序员提供了预先包装的数据结构和算法来操纵他们
集合是一个对象,可容纳其他对象的引用;集合接口声明对每一种类型的集合可以执行的操作
集合框架的类和接口均在java.util包中
任何对象加入集合类后,自动转变为Object类型,所以在取出的时候,需要进行强制类型转换
Java ArrayList
ArrayList类是一个可以动态修改的数组,于普通数组的区别就是它是没有固定大小的限制,我们可以添加或删除元素
ArrayList继承了AbstractList,并实现了List接口
ArrayList类位于java.util包中,使用前需要引入它,语法格式如下:
import java.util.ArrayList; // 引入 ArrayList 类ArrayList<E> objectName =new ArrayList<>(); // 初始化
- E:泛型数据类型,用于设置objectName的数据类型,只能为引用数据类型
- objectName:对象名
ArrayList是一个数组队列,提供了相关的添加、删除、修改、遍历等功能
添加元素
ArrayList类提供了很多有用的方法,添加元素到ArrayList可以使用add()方法:
import java.util.ArrayList;public class RunoobTest {public static void main(String[] args) {ArrayList<String> sites = new ArrayList<String>();sites.add("Google");sites.add("Runoob");sites.add("Taobao");sites.add("Weibo");System.out.println(sites);}}结果为[Google, Runoob, Taobao, Weibo]
访问元素
访问ArrayList中的元素可以使用get()方法
import java.util.ArrayList;public class RunoobTest {public static void main(String[] args) {ArrayList<String> sites = new ArrayList<String>();sites.add("Google");sites.add("Runoob");sites.add("Taobao");sites.add("Weibo");System.out.println(sites.get(1)); // 访问第二个元素}}结果为Runoob
修改元素
如果要修改ArrayList中的元素可以使用set()方法:
import java.util.ArrayList;public class RunoobTest {public static void main(String[] args) {ArrayList<String> sites = new ArrayList<String>();sites.add("Google");sites.add("Runoob");sites.add("Taobao");sites.add("Weibo");sites.set(2, "Wiki"); // 第一个参数为索引位置,第二个为要修改的值System.out.println(sites);}}结果为:[Google, Runoob, Wiki, Weibo]
删除元素
如果要删除ArrayList中的元素可以使用remove()方法:
import java.util.ArrayList;public class RunoobTest {public static void main(String[] args) {ArrayList<String> sites = new ArrayList<String>();sites.add("Google");sites.add("Runoob");sites.add("Taobao");sites.add("Weibo");sites.remove(3); // 删除第四个元素System.out.println(sites);}}结果为[Google, Runoob, Taobao]
计算大小
如果要计算ArrayList中的元素数量可以是使用size()方法
import java.util.ArrayList;public class RunoobTest {public static void main(String[] args) {ArrayList<String> sites = new ArrayList<String>();sites.add("Google");sites.add("Runoob");sites.add("Taobao");sites.add("Weibo");System.out.println(sites.size());}}结果为:4
迭代数组列表
我们可以使用for来迭代数组列表中的元素:
import java.util.ArrayList;public class RunoobTest {public static void main(String[] args) {ArrayList<String> sites = new ArrayList<String>();sites.add("Google");sites.add("Runoob");sites.add("Taobao");sites.add("Weibo");for (int i = 0; i < sites.size(); i++) {System.out.println(sites.get(i));}}}结果为:RunoobTaobao
也可以使用for-each来迭代元素:
import java.util.ArrayList;public class RunoobTest {public static void main(String[] args) {ArrayList<String> sites = new ArrayList<String>();sites.add("Google");sites.add("Runoob");sites.add("Taobao");sites.add("Weibo");for (String i : sites) {System.out.println(i);}}}结果为:RunoobTaobao
其他的引用类型
ArrayList中的元素实际上是对象,在以上实例中,数组列表元素都是字符串String类型。
如果我们要存储其他类型,而
基本类型对应的包装类表如下:
此外,bigInteger、BigDecimal用于高精度的运算,BigInteger支持任意精度的整数,也是引用类型,但它们没有相对应的基本类型
ArrayList<Integer> li=new Arraylist<>(); // 存放整数元素ArrayList<Character> li=new Arraylist<>(); // 存放字符元素
以下实例使用ArrayList存储数字(使用Integer类型·)
import java.util.ArrayList;public class RunoobTest {public static void main(String[] args) {ArrayList<Integer> myNumbers = new ArrayList<Integer>();myNumbers.add(10);myNumbers.add(15);myNumbers.add(20);myNumbers.add(25);for (int i : myNumbers) {System.out.println(i);}}}结果为:10152025
ArrayList排序
Collecations类也是一个非常有用的类,位于java.util包中,提供的sort()方法可以对字符或数组列表进行排序
以下实例对字母进行排序
import java.util.ArrayList;import java.util.Collections; // 引入 Collections 类public class RunoobTest {public static void main(String[] args) {ArrayList<String> sites = new ArrayList<String>();sites.add("Taobao");sites.add("Wiki");sites.add("Runoob");sites.add("Weibo");sites.add("Google");Collections.sort(sites); // 字母排序for (String i : sites) {System.out.println(i);}}}结果为:RunoobTaobaoWiki
以下实例对数字进行排序:
import java.util.ArrayList;import java.util.Collections; // 引入 Collections 类public class RunoobTest {public static void main(String[] args) {ArrayList<Integer> myNumbers = new ArrayList<Integer>();myNumbers.add(33);myNumbers.add(15);myNumbers.add(20);myNumbers.add(34);myNumbers.add(8);myNumbers.add(12);Collections.sort(myNumbers); // 数字排序for (int i : myNumbers) {System.out.println(i);}}}结果为:81215203334
Java ArrayList方法
Java LinkedList
链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的地址
链表可分为单向链和双向链表
一个单向链表包含两个值,当前节点的值和一个指向下一个节点的链接
一个·双向链表有三个整数值:数值、向后的节点链接、向前的节点链接
Java LinkedList(链表)类似于ArrayList,是一种常用的数据容器
于ArrayList相比,LinkedList的增加和删除对操作效率更高,而查找和修改的操作效率较低
以下情况使用ArrayList:
- 频繁访问列表种的某一个元素
- 只需要在列表末尾进行添加和删除元素操作
以下情况使用LinkedList:
- 你需要通过循环迭代来访问列表中的某些元素
- 需要频繁的在列表的开头、中间、末尾等位置进行添加和删除元素操作
LinkedList继承了AbstractSequentialList类
LinkedList实现了Queue接口,可作为队列使用
LinkedList实现了List接口,可进行列表的相关操作
LinkedList实现了Deque接口,可作为队列使用
LinkedList实现了Cloneable接口,可实现克隆
LinkedList实现了java.io.Serialzable接口,即可支持序列化,能通过序列化去传输
LinkedList类位于java.util包中,使用钱需要引入它,语法格式如下:
// 引入 LinkedList 类import java.util.LinkedList;LinkedList<E> list = new LinkedList<E>(); // 普通创建方法或者LinkedList<E> list = new LinkedList(Collection<? extends E> c); // 使用集合创建链表
创建一个简单的链表实例:
import java.util.LinkedList;public class RunoobTest {public static void main(String[] args) {LinkedList<String> sites = new LinkedList<String>();sites.add("Google");sites.add("Runoob");sites.add("Taobao");sites.add("Weibo");System.out.println(sites);}}结果为:[Google, Runoob, Taobao, Weibo]
更多的情况下使用ArrayList访问列表中的随机元素更加高效,但以下几种情况LinkedList提供了更高效的方法:
在列表开头添加元素:
// 引入 LinkedList 类import java.util.LinkedList;public class RunoobTest {public static void main(String[] args) {LinkedList<String> sites = new LinkedList<String>();sites.add("Google");sites.add("Runoob");sites.add("Taobao");// 使用 addFirst() 在头部添加元素sites.addFirst("Wiki");System.out.println(sites);}}结果为[Wiki, Google, Runoob, Taobao]
在列表结尾添加元素:
// 引入 LinkedList 类import java.util.LinkedList;public class RunoobTest {public static void main(String[] args) {LinkedList<String> sites = new LinkedList<String>();sites.add("Google");sites.add("Runoob");sites.add("Taobao");// 使用 addLast() 在尾部添加元素sites.addLast("Wiki");System.out.println(sites);}}结果为:[Google, Runoob, Taobao, Wiki]
在列表开头移除元素:
// 引入 LinkedList 类import java.util.LinkedList;public class RunoobTest {public static void main(String[] args) {LinkedList<String> sites = new LinkedList<String>();sites.add("Google");sites.add("Runoob");sites.add("Taobao");sites.add("Weibo");// 使用 removeFirst() 移除头部元素sites.removeFirst();System.out.println(sites);}}结果为:[Runoob, Taobao, Weibo]
在列表结尾移除元素:
// 引入 LinkedList 类import java.util.LinkedList;public class RunoobTest {public static void main(String[] args) {LinkedList<String> sites = new LinkedList<String>();sites.add("Google");sites.add("Runoob");sites.add("Taobao");sites.add("Weibo");// 使用 removeLast() 移除尾部元素sites.removeLast();System.out.println(sites);}}结果为:[Google, Runoob, Taobao]
获取列表开头的元素:
// 引入 LinkedList 类import java.util.LinkedList;public class RunoobTest {public static void main(String[] args) {LinkedList<String> sites = new LinkedList<String>();sites.add("Google");sites.add("Runoob");sites.add("Taobao");sites.add("Weibo");// 使用 getFirst() 获取头部元素System.out.println(sites.getFirst());}}结果为:
获取列表结尾的元素:
// 引入 LinkedList 类import java.util.LinkedList;public class RunoobTest {public static void main(String[] args) {LinkedList<String> sites = new LinkedList<String>();sites.add("Google");sites.add("Runoob");sites.add("Taobao");sites.add("Weibo");// 使用 getLast() 获取尾部元素System.out.println(sites.getLast());}}结果为:
迭代元素
我们可以使用for配合size()方法来迭代列表中的元素
// 引入 LinkedList 类import java.util.LinkedList;public class RunoobTest {public static void main(String[] args) {LinkedList<String> sites = new LinkedList<String>();sites.add("Google");sites.add("Runoob");sites.add("Taobao");sites.add("Weibo");for (int size = sites.size(), i = 0; i < size; i++) {System.out.println(sites.get(i));}}}结果为:RunoobTaobao
也可以使用for-each来迭代元素
// 引入 LinkedList 类import java.util.LinkedList;public class RunoobTest {public static void main(String[] args) {LinkedList<String> sites = new LinkedList<String>();sites.add("Google");sites.add("Runoob");sites.add("Taobao");sites.add("Weibo");for (String i : sites) {System.out.println(i);}}}结果为:RunoobTaobao
常用方法
Java HashSet
HashSet基于HashMap来实现的,是一个不允许有重复元素的集合
HashSet允许有null值
HashSet是无序的,即不会记录插入的顺序
HashSet不是线程安全的,如果多个线程尝试同时修改HashSet,则最终结果是不确定的,您必须在多线程访问时显式同步对HashSet的并发访问
HashSet实现了Set接口
HashSet中的元素实际上是对象,,一些常见的基本类型可以使用它的包装类
基本类型对应的包装类表如下:
HashSet类位于java.util包中,使用前需要引入它,语法格式如下:
import java.util.HashSet; // 引入 HashSet 类
以下实例我们创建一个HashSet对象sites,用于保存字符串元素
HashSet<String> sites = new HashSet<String>();
添加元素
HashSet类提供类很多有用的方法,添加元素可以使用add()方法
// 引入 HashSet 类import java.util.HashSet;public class RunoobTest {public static void main(String[] args) {HashSet<String> sites = new HashSet<String>();sites.add("Google");sites.add("Runoob");sites.add("Taobao");sites.add("Zhihu");sites.add("Runoob"); // 重复的元素不会被添加System.out.println(sites);}}结果为:[Google, Runoob, Zhihu, Taobao]
在上面的实例中,Runoob被添加了两次,它在集合中也只会出现一次,因为集合中的每个元素都必须是唯一的
判断元素是否存在
我们可以使用 contains() 方法来判断元素是否存在于集合当中
// 引入 HashSet 类import java.util.HashSet;public class RunoobTest {public static void main(String[] args) {HashSet<String> sites = new HashSet<String>();sites.add("Google");sites.add("Runoob");sites.add("Taobao");sites.add("Zhihu");sites.add("Runoob"); // 重复的元素不会被添加System.out.println(sites.contains("Taobao"));}}结果为:true
删除元素
// 引入 HashSet 类import java.util.HashSet;public class RunoobTest {public static void main(String[] args) {HashSet<String> sites = new HashSet<String>();sites.add("Google");sites.add("Runoob");sites.add("Taobao");sites.add("Zhihu");sites.add("Runoob"); // 重复的元素不会被添加sites.remove("Taobao"); // 删除元素,删除成功返回 true,否则为 falseSystem.out.println(sites);}}结果为:[Google, Runoob, Zhihu]
删除集合中所以元素可以使用 clear 方法:
// 引入 HashSet 类import java.util.HashSet;public class RunoobTest {public static void main(String[] args) {HashSet<String> sites = new HashSet<String>();sites.add("Google");sites.add("Runoob");sites.add("Taobao");sites.add("Zhihu");sites.add("Runoob"); // 重复的元素不会被添加sites.clear();System.out.println(sites);}}结果为:[]
计算大小
如果要计算HashSet中的元素数量可以使用size()方法
// 引入 HashSet 类import java.util.HashSet;public class RunoobTest {public static void main(String[] args) {HashSet<String> sites = new HashSet<String>();sites.add("Google");sites.add("Runoob");sites.add("Taobao");sites.add("Zhihu");sites.add("Runoob"); // 重复的元素不会被添加System.out.println(sites.size());}}结果为:4
迭代HashSet
可以使用 for-each来迭代 HashSet中的元素
// 引入 HashSet 类import java.util.HashSet;public class RunoobTest {public static void main(String[] args) {HashSet<String> sites = new HashSet<String>();sites.add("Google");sites.add("Runoob");sites.add("Taobao");sites.add("Zhihu");sites.add("Runoob"); // 重复的元素不会被添加for (String i : sites) {System.out.println(i);}}}结果为:RunoobZhihuTaobao
Java HashMap
HashMap是散列表,它存储的内容是键值对(key-value)映射
HashMap实现了Map接口,根据键的HashCode值存储数据,具有很快的访问速度,最多允许一条记录的键为null,不支持线程同步
HashMap是无序的,即不会记录插入的顺序
HashMap继承于AbstractMap,实现了Map、Cloneable、java.io.Serializable接口
HashMap的key与value类型可以相同也可以不同,可以是字符串(String)类型的key和value,也可以是整型(Integer)的key与字符串(String)类型的value
HashMap中的元素实际上是对象,一些常见的基本类型可以使用它的包装类
基本类型对应的包装类表如下:
HashMap类位于java.util包中,使用前需要引入它,语法格式如下:
import java.util.HashMap; // 引入 HashMap 类
以下实例我们创建一个HashMap对象Sites,整型(Integer)的key和字符串(String)类型的value:
HashMap<Integer, String> Sites = new HashMap<Integer, String>();
添加元素
HashMap类提供类很多有用的方法,添加键值对(key-value)可以使用put()方法:
// 引入 HashMap 类import java.util.HashMap;public class RunoobTest {public static void main(String[] args) {// 创建 HashMap 对象 SitesHashMap<Integer, String> Sites = new HashMap<Integer, String>();// 添加键值对Sites.put(1, "Google");Sites.put(2, "Runoob");Sites.put(3, "Taobao");Sites.put(4, "Zhihu");System.out.println(Sites);}}结果为:{1=Google, 2=Runoob, 3=Taobao, 4=Zhihu}
以下实例创建一个字符串(String)类型的key和字符串(String)类型的value:
import java.util.HashMap;public class RunoobTest {public static void main(String[] args) {// 创建 HashMap 对象 SitesHashMap<String, String> Sites = new HashMap<String, String>();// 添加键值对Sites.put("one", "Google");Sites.put("two", "Runoob");Sites.put("three", "Taobao");Sites.put("four", "Zhihu");System.out.println(Sites);}}结果为:{four=Zhihu, one=Google, two=Runoob, three=Taobao}
访问元素
我们可以使用get(key)方法来获取key对应的value:
import java.util.HashMap;public class RunoobTest {public static void main(String[] args) {// 创建 HashMap 对象 SitesHashMap<Integer, String> Sites = new HashMap<Integer, String>();// 添加键值对Sites.put(1, "Google");Sites.put(2, "Runoob");Sites.put(3, "Taobao");Sites.put(4, "Zhihu");System.out.println(Sites.get(3));}}结果为:Taobao
删除元素
我们可以使用remove(key)方法来删除key对应的键值对(key-value):
import java.util.HashMap;public class RunoobTest {public static void main(String[] args) {// 创建 HashMap 对象 SitesHashMap<Integer, String> Sites = new HashMap<Integer, String>();// 添加键值对Sites.put(1, "Google");Sites.put(2, "Runoob");Sites.put(3, "Taobao");Sites.put(4, "Zhihu");Sites.remove(4);System.out.println(Sites);}}结果为:{1=Google, 2=Runoob, 3=Taobao}
删除所有键值对(key-value)可以使用clear方法:
// 引入 HashMap 类import java.util.HashMap;public class RunoobTest {public static void main(String[] args) {// 创建 HashMap 对象 SitesHashMap<Integer, String> Sites = new HashMap<Integer, String>();// 添加键值对Sites.put(1, "Google");Sites.put(2, "Runoob");Sites.put(3, "Taobao");Sites.put(4, "Zhihu");Sites.clear();System.out.println(Sites);}}结果为:{}
计算大小
如果要计算HashMap中的元素数量可以使用size()方法:
import java.util.HashMap;public class RunoobTest {public static void main(String[] args) {// 创建 HashMap 对象 SitesHashMap<Integer, String> Sites = new HashMap<Integer, String>();// 添加键值对Sites.put(1, "Google");Sites.put(2, "Runoob");Sites.put(3, "Taobao");Sites.put(4, "Zhihu");System.out.println(Sites.size());}}结果为:4
迭代HashMap
可以使用for-each来迭代HashMap中的元素
如果你只想获取key,可以使用keySet()方法,然后可以通过get(key)获取对应的value,如果你只想获取value,可以使用values()方法
import java.util.HashMap;public class RunoobTest {public static void main(String[] args) {// 创建 HashMap 对象 SitesHashMap<Integer, String> Sites = new HashMap<Integer, String>();// 添加键值对Sites.put(1, "Google");Sites.put(2, "Runoob");Sites.put(3, "Taobao");Sites.put(4, "Zhihu");// 输出 key 和 valuefor (Integer i : Sites.keySet()) {System.out.println("key: " + i + " value: " + Sites.get(i));}// 返回所有 value 值for(String value: Sites.values()) {// 输出每一个valueSystem.out.print(value + ", ");}}}结果为:key: 1 value: Googlekey: 2 value: Runoobkey: 3 value: Taobaokey: 4 value: ZhihuGoogle, Runoob, Taobao, Zhihu,
Java HashMap方法
常用方法列表如下:



