集合框架
集合类概述
为什么出现集合类?
面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,Java就提供了集合类
- 数组和集合类同是容器,有何不同?
数组虽然也可以存储对象,但长度是固定的;集合长度是可变的。数组中可以存储基本数据类型,集合只能存储对象。
集合类的特点
集合只用于存储对象,集合长度是可变的,集合可以存储不同类型的对象。
Collection 接口
Collection 是最基本集合接口,它定义了一组允许重复的对象。Collection 接口派生了两个子接口Set和 List
Collection接口的方法
Collection接口中的方法是集合中所有实现类必须拥有的方法
集合普通方法
- boolean add(Object e):向集合中添加一个元素
- boolean remove(Object o):删除该集合中指定的元素元素
- void clear():清空集合
- boolean contains(Object o):判断集合中是否包含某个元
- boolean isEmpty():判断集合是否为空
- int size():获取集合内元素的数量
代码示例
public void T1(){
Collection list = new ArrayList();
//add(Object e):向集合中添加一个元素 ,返回的是boolean类型
System.out.println(list.add("张三"));
System.out.println(list.add("张三1"));
System.out.println(list.add("张三2"));
System.out.println(list.add("张三3"));
System.out.println(list.add("张三4"));
System.out.println(list.add("张三5"));
System.out.println(list.add("张三6"));
System.out.println(list.add("张三7"));
System.out.println(list.add("张三8"));
//boolean remove(Object o):删除该集合中指定的元素元素 ,返回值是boolean类型,如果本来就不含有所需删除的就返回false
// System.out.println(list.remove("张三"));
// System.out.println(list.remove("三"));
//void clear():清空集合
// list.clear();
//boolean contains(Object o):判断集合中是否包含某个元素,返回真或假
System.out.println("判断是否含有元素!");
System.out.println(list.contains("张三5"));
System.out.println(list.contains("李四"));
//boolean isEmpty():判断集合是否为空
System.out.println(list.isEmpty());
//int size():获取集合内元素的数量 ,返回的是一个int型整数
System.out.println(list.size());
//打印整个集合
System.out.println(list);
}
集合批量操作方法
- boolean addAll(Collection
代码示例
public void T2(){
Collection lit1 = new ArrayList();
lit1.add("小明");
lit1.add("小红");
lit1.add("小黄");
lit1.add("小蓝");
lit1.add("小绿");
System.out.println(lit1);
Collection lit2 = new ArrayList();
lit2.add("大黄");
lit2.add("大红");
lit2.add("小黄");
lit2.add("大蓝");
lit2.add("小绿");
System.out.println(lit2);
Collection lit3 = new ArrayList();
lit3.add("小花");
//boolean addAll(Collection<? extends E> e):将指定collection中的所有元素都添加到此collection中
lit1.addAll(lit2);
System.out.println("lit1:"+lit1 );
//boolean containsAll(Collection<?> e)如果此collection包含指定collection中的所有元素,则返回true
System.out.println(lit1.containsAll(lit2));
//boolean removeAll(Collection<?> e):移除此collection中那些也包含在指定collection中的所有元素(可选操作)
System.out.println(lit1.removeAll(lit2));
System.out.println(lit1);
// boolean retainAll(Collection<?> e):仅保留此collection中那些也包含在指定collection的元素(可选操作)
System.out.println(lit1);
System.out.println(lit2);
System.out.println(lit1.retainAll(lit2));
System.out.println(lit1);
//Object[] toArray() 返回包含此collection中所有元素的数组
System.out.println(lit1.containsAll(lit2));
}
Collection接口存储自定义对象
示例代码
public class Demo {
public static void main(String[] args) {
//1.实例化一个集合
Collection list = new ArrayList();
//2.填充集合
list.add(new Student("李四",20));
list.add(new Student("王五",22));
list.add(new Student("赵六",24));
list.add(new Student("田七",26));
System.out.println(list);
}
}
public class Student {
String name;
int age;
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
}
Collection遍历方式
Collection遍历有两种方式
1. 将结合转成数组
2. 使用迭代器
使用数组
示例代码
public void T3(){
//使用数组遍历
Collection lit1 = new ArrayList();
lit1.add("小明");
lit1.add("小红");
lit1.add("小黄");
lit1.add("小蓝");
lit1.add("小绿");
Object[] li = lit1.toArray();
System.out.println(Arrays.toString(li));
for(int i = 0;i<li.length;i++){
System.out.println(li[i]);
}
}
迭代器
在 Java 中,有很多的数据容器,对于这些的操作有很多的共性。Java 采用了迭代器来为各种容器提供了公共的操作接口。这样使得对容器的遍历操作与其具体的底层实现相隔离,达到解耦的效果。
在Iterator接口中定义了三个方法:
boolean hasNext() 如果仍有元素可以迭代,则返回true.
E next() 返回迭代的下一个元素
void remove()从迭代器指向的collection中移除迭代器返回的最后一个元素(可选操作)。
注意:Java中的Iterator只能单向移动
collection获取迭代器方法
Iterator iterator() 返回在此collection的元素上进行迭代的迭代器
示例代码
public void T4(){
Collection lit1 = new ArrayList();
lit1.add("小明");
lit1.add("小红");
lit1.add("小黄");
lit1.add("小蓝");
lit1.add("小绿");
Iterator it = lit1.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
增强 for
foreach 语句是 java5 的新特征之一,在遍历数组、集合方面,foreach 为开发人员提供了极大的方便。
foreach语句是for语句的特殊简化版本,但是 foreach语句并不能完全取代 for语句,然而,任何的foreach语句都可以改写为for语句版本。
foreach的语句格式:
for(元素类型 元素变量名 : 遍历对象){
使用元素变量进行操作
}
优点:
- 简化编程操作
- 提高代码安全性(越界异常)
缺点:
- 无法对索引进行操作
示例代码
public void T5(){
Collection lit1 = new ArrayList();
lit1.add("小明");
lit1.add("小红");
lit1.add("小黄");
lit1.add("小蓝");
lit1.add("小绿");
for (Object object : lit1) {
System.out.println(object);
}
}
List接口
List接口为Collection直接接口。
List所代表的是有序的 Collection,即它用某种特定的插入顺序 “维护元素顺序”。
用户可以对列表中每个元素的插入位置进行精确地控制,同时可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。
实现List接口的集合主要有:ArrayList、LinkedList、Vector、Stack。
List集合特有的功能
list添加了很多针对下标(index)操作的方法
void add(int index,E element) 在列表的指定位置插入指定元素(可选操作)
E get(int index) 返回列表中指定位置的元素
E remove(int index) 移除列表中指定位置的元素(可选元素)
E set(int index, E element)用指定元素替换列表中指定位置的元素(可选操作)
示例代码
public void T1(){
/*void add(int index,E element) 在列表的指定位置插入指定元素(可选操作)
* E get(int index) 返回列表中指定位置的元素
* E remove(int index) 返回列表中指定位置的元素(可选元素)
* E set(int index, E element)用指定元素替换列表中指定位置的元素(可选操作) *
*/
List list = new ArrayList<>();
list.add("aaa");// Collection
list.add("bbb");// Collection
list.add("ccc");// Collection
System.out.println(list);
//在索引为1的位置插入“11234”
list.add(1,"11234");
System.out.println(list);
//返回索引为3的元素
System.out.println(list.get(3));
//
System.out.println(list);
list.remove(3);
System.out.println(list);
//指定元素替换列表中指定位置的元素
list.set(2, "32435");
System.out.println(list);
}
List的特有遍历功能
List基础自Collection接口,所以越继承了父接口的两个变量方式
1. toArray() 转数组
2. iterator() 迭代器
除此之外,List还新增了一种迭代器方式
ListIterator listIterator()
ListIterator是Iterator 的子接口;它继承了 Iterator的所有方法;
另外还新增了几个方法:
1. E previous():返回列表中的前一个元素;
2. boolean hasPrevious():判断是否有前一个元素;
3. 特点
1. Iterator:单项的,只能向下遍历;
2. ListIterator:双向的;可以向下遍历,也可以向上遍历;
注意:ListIterator只适用于List集合
示例代码
public void T2(){
List list = new ArrayList<>();
list.add("aaa");// Collection
list.add("bbb");// Collection
list.add("ccc");// Collection
ListIterator it = list.listIterator();
//向下遍历
while(it.hasNext()){
System.out.println(it.next());
}
System.out.println("-----------------------");
//向上遍历
while(it.hasNext()){
it.next();
}
while(it.hasPrevious()){
System.out.println(it.previous());
}
}
通常是当我们使用”迭代器”遍历集合时,通过”集合对象”去修改集合中的元素,这时,就会产生并发修改异常
解决方式:
通过迭代器遍历,就通过迭代器去修改
示例代码
public void T3(){
List list = new ArrayList();
list.add("李四");
list.add("王五");
list.add("赵六");
ListIterator it = list.listIterator();
while (it.hasNext()) {
String str = (String) it.next();
if (str.equals("李四")) {
// 向集合中添加一个元素:田七
// list.add("田七");//此处会发生修改异常:ConcurrentModificationException
it.add("田七");
}
}
System.out.println(list);
}
ArrayList
ArrayList是List接口的一个实现类,它是程序中最常见的一种集合,内部封装了一个长度可变的数组对象,当存入的元素超过数组长度时,ArrayList 会在内存中分配一个更大的数组来存储这些元素。因此 ArrayList集合看做一个长度可变的数组。
特点:
1. 底层数据结构是数组,随机访问速度快(根据索引访问),插入和移除较慢。
2. 插入的数据有顺序,元素可以重复
3. 线程不安全,效率高。(线程讲解)
为什么效率低?
- 数组结构的优点是便于对集合进行快速的随机访问,如果经常需要根据索引位置访问集合中的对象,使用由ArrayList类实现的 List集合的效率较好。
- 数组结构的缺点:在向指定索引位置插入、删除指定对象效率较慢,如果经常需要向 List 集合的指定索引位置插入或删除对象,那么使用由 ArrayList 类实现的List 集合的效率则较低,并且插入、删除对象的索引位置越小效率越低,原因是当向指定的索引位置插入对象时,会同时将指定索引位置及之后的所有对象相应的向后移动一位。
示例代码
public void T1() {
// 1.创建ArrayList集合
ArrayList<String> list = new ArrayList<String>();
// 2.添加
list.add("Java");
list.add("PHP");
list.add("Python");
// 3.删除
list.remove(1);
// 4.遍历
// 4.1 for
System.out.println("普通 for 循环迭代:");
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
// 4.2 增强for
System.out.println("增强for 迭代:");
for (String s : list) {
System.out.println(s);
}
// 4.3 迭代器
System.out.println("Iterator 迭代器:");
Iterator<String> it = list.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
// 4.4 list迭代器
System.out.println("listIterator 迭代器:");
ListIterator<String> lit = list.listIterator();
while (lit.hasNext()) {
lit.next();
}
while (lit.hasPrevious()) {
System.out.println(lit.previous());
}
// 3.打印集合
// System.out.println(list);
}
LinkedList
ArrayList 集合在查询元素时速度很快,但在删除时效率较低,为了克服这种局限性,可以使用LinkedList。
LinkedList内部维护了一个双向循环链表,链表中的每一个元素彼此相连起来。插入和删除元素只需要修改元素之间的应用关系即可。
特点:
1. 增删效率很高
2. 查询效率低
LinkedList特有方法
因为是链表结构,所以 LinkedList提供了一些首尾操作的方法。
直接上代码~~
示例代码:
public void t1() {
// 1.创建 LinkedList集合
LinkedList list = new LinkedList();
// 2.填充集合
list.add("黑豹");
list.add("美国队长");
list.add("鹰眼");
list.add("钢铁侠");
list.add("浩克");
// 特有的存储的方法
list.addFirst("漫威宇宙的英雄:");
list.addLast("还有很多。。");
// 特有的获取元素的方法
System.out.println(list.getFirst());
System.out.println(list.getLast());
// 特有的删除的方法
System.out.println(list.removeFirst()); // 返回删除的元素
System.out.println(list.removeLast());
System.out.println(list);
}