本篇只负责讲一些Java集合框架基础内容,后面的详细内容在后面的篇章进行讲解,学集合的小妙招,看完代码直接自己敲一遍,绝对简单
目录
一.Java集合概述
1.1 Java中使用数组的缺陷
在Java中如果使用数组有较多缺陷,如:
- 数组长度固定不变
数组一旦创建,长度就是固定不变的,为了能存储更多的信息,可以将数组长度定义为足够大,但是这样会浪费内存空间,不够灵活。所以当需要保存数量变化的一组数据时,数组就无能为力了。
- 不便存储具有映射关系的数据
有时为了记录数据和查询方便,会对例如水果编号,形成与其品种具有映射关系的数据,例如,AP001——富士苹果,AP00——金帅苹果,PE00——果梨等,这样可以方便通过编号进行查询。这种数据看起来像两个数组,但是这两个数组的元素之间是有一定关联的,实现起来非常不方便。
- 数据变更效率低下
数组在内存中被分配的是连续的存储控件,根据下标可以快速遍历信息列表,但是如果执行插入或删除操作,就会因频繁地进行数据移位操作而效率低下。
综上所述,数组在存储数据时,虽然具有其优势,但在特定场合下也存在着明显的不足,为了解决这些问题,Java提供了集合类,主要负责在不同应用场景下解决数据存储的问题,因此集合类类也被称为容器类。使用集合存储数据解决了数组长度固定的问题,并且它是高性能的,容易实现扩展和修改。
1.2 集合框架
1.2.1 Java集合框架主要内容
Java集合框架提供了一套性能优良、使用方便的接口和类,它们都位于java.util包中,集合中的元素全部是对象,即Object类的实例,不同的集合类有不同的功能和特点,适合不同的场合。Java集合框架包含的主要内容如下所示:
Iterator(迭代器)
Iterator(这是用来遍历(取值)Collection集合的迭代器,在后面进行讲解,不过有一点点复杂,一般不使用这个,而是foreach循环或还有另一种可以直接用for循环的方式)
Collection接口
这个就是我们常用的集合接口,它有两个子接口,分别是List和Set,这两个我们都放在后面进行详解,前面会有一些简单的介绍(List是比较常用的);
List接口
List接口有两个实现类,分别是ArrayList和LinkedList,这两个我们放在后面进行细说;
Set接口
Set接口也有两个实现类,分别是HashSet和TreeSet,这两个我们也放在后面进行细说;
Map接口
Map接口也有两个实现类,分别是HashMap和TreeMap,这两个我们也放在后面进行细说;
- 如上只显示Java集合框架中常用的接口和类,省略了部分中间类。如有需要,可查询JDK1.8帮助文档。
- Map接口独立于Collection接口,但属于集合框架中的一部分
- 从以上内容可以看出,Java的集合类主要由两个接口派生而成:Collection接口和Map接口。Collection接口和Map接口是Java集合框架的根接口,这两个接口包括了一些子接口或实现类。其中,Collection接口常用的子接口包含List接口和Set接口;另外一个重要接口是Map接口,它是独立一支,以上三者都是集合接口,其实现类为Java中经常使用的集合类型。Java集合框架常用接口说明如下所示。此外,Java集合框架还包括相关的工具类(Iterator迭代器接口、Arrays类和Collections类)
1.2.2 Java集合框架常用接口
Collection
- 单值集合的根接口,是最基本的集合接口。
- 一个Collection代表一组Object。Java不提供其实现类,只提供子接口(如List接口和Set接口)
- Collection接口存储一组可重复的无序对象
Set
- 继承Collection接口,存储一组不可重复的无序对象
List
- 继承Collection接口,存储一组可重复的有序对象
- 元素顺序以元素插入的次序来放置元素,不会重新排序
- 通过索引访问数组元素,索引从0开始
- List接口常用的实现类有ArrayList类和LinkedList类
Map
- 存储成对数据的根接口,可存储一组"键-值"对象。(就像身份证号对应名字一样,身份证号就是键,可以根据身份证号来找到对应的名字,名字就是值,名字可以重复有,但是身份证号没有重复的)
- 提供键(key)到值(value)的映射,Map中的键不要求有序,不允许重复。值同样不要求有序,但允许重复。
- 可以通过键找到对应的值。
Iterator
- 集合迭代器,能够遍历集合元素的接口。
Collections
- 与Collection是不同的概念,它提供了对集合对象进行基本操作的通用接口方法。
- 包含各种有关集合操作的静态方法。
- 是一个工具类,不能实例化。
在后面将使用接口名命名此接口的实现类组成的集合,例如,List集合为List接口所有实现类(ArrayList类和LinkedList类)组成的集合,同理,Set集合为Set接口的所有实现类组成的集合。
1.3 Collection接口
Collection接口是List接口、Set接口的父接口,该接口中定义的方法既可用于操作Set集合,也可用于操作List集合。Collection接口常用的方法如下:
1.3.1 常用方法
1.3.2 案例
观察此案例就可理解Collection接口的常用方法是大概如何使用
打印结果
1.4 集合的遍历
当使用System.out.println()方法输出集合对象时,其将以[1,1,...]的形式输出,这是因为所有的Collection实现类都重写了toString()方法,该方法可以一次性地输出集合中的所有元素。但是,如果想依次访问集合里的每一个元素,并实现对该元素的操作,则需要使用某种方式遍历集合元素。下面将介绍两个方法。
1.4.1 使用Iterator(迭代器)接口遍历集合元素
Iterator接口也是Java集合框架的成员,但它与集合不一样。集合主要用于存储其他对象,而Iterator接口主要用于遍历(迭代访问)Collection集合中的元素,Iterator对象也被称为迭代器。
Iterator接口隐藏了各种Collection实现类的底层细节,向应用提供了遍历Collection集合元素的统一编程接口。Iterator接口定义了以下两个常用方法:
boolean hasNext()
- 判断是否存在下一个遍历元素,存在则返回true
Object next()
- 返回遍历的当前元素
若有一个Iterator对象,则必然有一个与之关联的Collection集合。没有集合的Iterator接口就像五本之木,无法发挥作用。
1.4.2 使用增强for循环遍历集合元素
除可以使用Iterator接口遍历Collection集合中的元素外,使用foreach循环遍历集合元素会更加便捷。foreach循环是JDK1.5引入的语法结构,也被称为增强for循环,可用于遍历集合和数组。其语法如下:
for(数据类型 type 迭代变量名 value:迭代对象 object){
//引用迭代变量value的语句
}
1.4.3 案例奉上

1.4.4 集合遍历的超简单语法(敲完代码再看噢)
不管使用Iterator迭代器遍历集合还是foreach遍历集合,只要记得一个口令,循,存,转,调就行了;
二.List
List集合为列表类型,以线性方式存储对象。List集合中的元素允许重复,各元素的顺序就是对象插入的顺序。用户可以通过使用索引来访问List集合中的元素。
2.1主要方法
对于由Collection定义的add()和addAll()方法外,List增加了方法add(int,Object)和addAll(int,Collection),这俩方法可以在指定的下标处插入元素。
List集合的特点就是存取有序,可以存储重复的元素,可以用下标进行元素的操作
2.2ArrayList集合
ArrayList支持可随需要而增长的动态数组。在Java数组中,长度是固定的,因此在数组被创建后,不能修改长度,这意味着开发者需要实现知道数组的长度。但在一般情况下,只有在运行时才知道数组长度。为了解决这个问题,ArrayList因此而生。
2.2.1代码演示
class Test{
public static void main(String[] args) {
ArrayList<String> list1 = new ArrayList<>();
System.out.println("list1初始长度为:"+ list1.size());
list1.add("A");
list1.add("B");
list1.add("C");
list1.add("D");
list1.add("E");
list1.add("F");
//将B2添加在list1的index=1的位置
list1.add(1, "B2");
System.out.println("list1加入元素后的大小:" + list1.size());
System.out.println("list1元素为:"+ list1);
list1.remove("A");
list1.remove(2);
System.out.println("list1删除元素后的大小:" + list1.size());
System.out.println("list1元素为:" + list1);
}
}
Output:
list1初始长度为:0
list1加入元素后的大小:7
list1元素为:[A, B2, B, C, D, E, F]
list1删除元素后的大小:5
list1元素为:[B2, B, D, E, F] // 需要移动数据,使得B2作为index=0的元素。
注意,list1开始为空,随着元素的加入,大小增加。当每个元素被删除时,大小会每次变小。
底层是使用数组实现,所以查询速度快,增删速度慢。
2.3ArrayList如何存入自定义的数据?
import java.util.ArrayList;
import java.util.Iterator;
public class Student{
private String name;
private int id;
public Student(){}
public Student(String name, int id)
{
super();
this.name = name;
this.id = id;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public int getId()
{
return id;
}
public void setId(int id)
{
this.id = id;
}
}
class Test{
public static void main(String []args) {
ArrayList<Student> list1 = new ArrayList<>();
list1.add(new Student("lili",001));
list1.add(new Student("haha",002)); //匿名对象存入集合
list1.add(new Student("wawa",003));
Iterator<Student> it=list1.iterator();
while(it.hasNext()) {
Student stu = it.next();
System.out.println(stu.getName()+stu.getId());
}
2.4LinkedLIst集合
除了LinkedList继承的方法以外,它本身还定义了一些有用的方法。
- addFirst()可以在列表头增加元素
- addLast()可以在列表尾部增加元素
- getFirst()可以获取第一个元素
- removeFirst()可以删除第一个元素
- removeLast()可以删除最后一个元素
- getFirst() 返回此列表的第一个元素
- getLast() 返回此列表的最后一个元素
LinkedList:是基于链表结构实现的,所以查询速度慢,增删速度快,提供了特殊的方法,对头尾的元素操作(进行增删查)
使用LinkedList实现栈
import java.util.LinkedList;
public class MyStack {
private LinkedList<String> linkList = new LinkedList<String>();
// 压栈
public void push(String str){
linkList.addFirst(str);
}
// 出栈
public String pop(){
return linkList.removeFirst();
}
// 查看
public String peek(){
return linkList.peek();
}
// 判断是否为空
public boolean isEmpty(){
return linkList.isEmpty();
}
}
public class Test {
public static void main(String[] args) {
StackTest stack = new StackTest();
stack.push("first");
stack.push("second");
stack.push("third");
stack.push("forth");
stack.push("fifth");
// 取出
while (!stack.isEmpty()){
String pop = stack.pop();
System.out.println(pop);
}
}
}
Output
fifth
fourth
third
second
first
也可实现队列。
2.5ArrayList和LinkedLIst
- ArrayList和LinkedList顾名思义,ArrayList是Array(动态数组)的数据结构,相当于动态数组;LinkedList是Link(链表)的双向数据结构,也可当作堆栈、队列、双端队列。
- 对于随机访问List时(get和set操作),ArrayList比LinkedList的效率更高,因为LinkedList是线性的数据存储方式,所以需要移动指针从前往后依次查找。
- 对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据(可以在上述ArrayList代码中体现)。
- 两者缺点都为线性不安全
ArrayList和LinkedList线程不安全,在多线程中不建议使用。
后续将继续补充集合的其他框架!!!