第四章、Collection集合(单个方式存储元素)
一、创建集合
在Java中,可以使用多种方式来创建一个集合对象,具体取决于你想要使用的集合类型和需求。下面列举了几种常见的创建集合的方式:
1、使用具体的集合实现类的构造方法
可以直接实例化具体的集合实现类,例如ArrayList、LinkedList、HashSet等。
ArrayList<String> arrayList = new ArrayList<>(); // 创建一个ArrayList集合
HashSet<Integer> hashSet = new HashSet<>(); // 创建一个HashSet集合
2、使用Collection,List,Set,SortedSet接口的实现类的构造方法
Collection是一个接口,但是你可以通过具体的实现类来实例化集合对象。
Collection<String> collection = new ArrayList<>(); // 创建一个ArrayList集合
二、集合遍历/迭代器(Iterator接口)
- 以下的遍历方式/迭代方式,是所有Collection集合的通用方式,在Map集合中不能用,在所有的Collection及其子类中使用
- 在Java中,迭代器(Iterator)是一种用于遍历集合(Collection)元素的对象。它提供了一些方法来逐个访问集合中的元素。
1、集合对象实例方法 iterator( ):获取集合对象的迭代器对象
//创建集合对象
Collection c = new ArrayList(); //后面的集合无所谓,主要是看前面的接口,怎么迭代
//第一步:获取集合对象的迭代器对象
Iterator it = c.iterator();
System.out.println(it); //java.util.ArrayList$Itr@7ef20235
2、boolean hasNext():该方法用于检查迭代器中是否还有下一个元素。如果有下一个元素,则返回true;否则,返回false
//创建集合对象
Collection c = new ArrayList();
c.add(1);
c.add(2);
Iterator it = c.iterator();
boolean flag = it.hasNext();
it.next();
System.out.println(flag); //true
flag = it.hasNext();
it.next();
System.out.println(flag); //true
flag = it.hasNext();
System.out.println(flag); //false
3、E next():该方法用于返回迭代器中的下一个元素,并将迭代器的位置移动到下一个元素。(E泛型默认为Object,泛型类型擦除)
while (it.hasNext()){
Object obj = it.next();
System.out.println(obj); //1 2
}
//运行时异常: java.util.NoSuchElementException
// while (true){
// Object obj = it.next();
// System.out.println(obj);
// }
4、void remove():该方法用于从集合中移除迭代器当前next返回的元素。此方法只能在调用next()之后,并且在同一次迭代中只能调用一次。
- 在迭代集合元素的过程中,一定要使用迭代器对象的remove() 方法来删除元素,不能使用集合对象的remove()方法来删除元素
- 需要注意的是,如果在迭代器的
next()方法之前调用了remove()方法,或者在同一次迭代中多次调用remove()方法,都会导致IllegalStateException(非法状态)异常的抛出。

package com.javase.collection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/**
* 关于集合元素的remove
* 集合就像快照一样,当集合结构发生改变时,必须重新获取迭代器,否则调用next()方法:java.util.ConcurrentModificationException,并发修改异常
*
* 在迭代集合元素的过程中,不能调用集合对象的remove方法,删除元素;
* c.remove(); 迭代过程中不能这样
* 会出现:java.util.ConcurrentModificationException
*
* 在迭代集合元素的过程中,一定要使用迭代器对象的remove方法来删除元素
*/
public class CollectionTest06 {
public static void main(String[] args) {
//创建集合
Collection c = new ArrayList();
/**
* 注意:此时获取的迭代器,指向的是集合中没有元素状态下的迭代器
* 一定要注意:集合结构只要发生改变,迭代器必须重新获取
* 当集合结构发生改变,迭代器没有重新获取时,调用next()方法:java.util.ConcurrentModificationException
*/
// Iterator it = c.iterator();
//添加元素
c.add(1); //Integer类型,自动装箱
c.add(2);
c.add(3);
//循环集合
Iterator it = c.iterator();
while (it.hasNext()){
//编写代码时next()方法返回值类型必须是Object
//因为泛型类型擦除为Object
Object obj = it.next();
System.out.println(obj); //1 2 3
}
Collection c2 = new ArrayList();
c2.add("abc");
c2.add("def");
c2.add("xyz");
Iterator it2 = c2.iterator();
while (it2.hasNext()){
Object obj = it2.next();
//删除元素
//删除元素之后,集合的结构发生了变化,应该重新获取迭代器
//但是,循环下一次的时候并没有重新获取迭代器,所以会出现异常:java.util.ConcurrentModificationException
// c2.remove(obj); //直接通过集合去删除元素,没有通知迭代器(导致迭代器的快照和原集合状态不同。)
//迭代器删除时,会自动更新迭代器,并且更新原集合
it2.remove();
System.out.println(obj); //abc def xyz
}
System.out.println(c2.size()); //0
}
}
5、迭代器执行原理

6、不使用泛型的情况下迭代器的next()方法,返回默认为Object类型
package com.javase.collection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
/**
* 关于集合遍历/迭代专题
*/
public class CollectionTest02 {
public static void main(String[] args) {
//注意:以下讲解的遍历方式/迭代方式,是所有的Collection通用的方式
//在Map集合中不能用,在所有的Collection及其子类中使用
//创建集合对象
Collection c = new ArrayList(); //后面的集合无所谓,主要是看前面的接口,怎么迭代
//添加元素
c.add("abc");
c.add("def");
c.add(100);
c.add(new Object());
//对集合Collection进行遍历/迭代
//第一步:获取集合对象的迭代器对象
Iterator it = c.iterator();
//第二步:通过获取的迭代器对象开始迭代/遍历
/**
* 以下两个方法是迭代器对象Iterator中的方法:
* boolean hasNext() 如果仍有元素可迭代,则返回true
* Object next() 返回迭代的下一个元素
*/
/*boolean hasNext = it.hasNext();
System.out.println(hasNext);
if(hasNext){
//不管你当初存进去什么,取出来统一都是Object
Object obj = it.next();
System.out.println(obj);
}
hasNext = it.hasNext();
System.out.println(hasNext);
if(hasNext){
Object obj = it.next();
System.out.println(obj);
}
hasNext = it.hasNext();
System.out.println(hasNext);
if(hasNext){
Object obj = it.next();
System.out.println(obj);
}
hasNext = it.hasNext();
System.out.println(hasNext);
if(hasNext){
Object obj = it.next();
System.out.println(obj);
}
hasNext = it.hasNext();
System.out.println(hasNext);
if(hasNext){
Object obj = it.next();
System.out.println(obj);
}*/
while (it.hasNext()){
Object obj = it.next();
System.out.println(obj);
}
//运行时异常: java.util.NoSuchElementException
// while (true){
// Object obj = it.next();
// System.out.println(obj);
// }
}
}
7、存进去的是什么类型,取出来的还是什么类型,只不过输出的时候会转换成字符串
package com.javase.collection;
import java.util.*;
public class CollectionTest03 {
public static void main(String[] args) {
//ArrayList集合特点;有序可重复
//创建集合
Collection c = new ArrayList();
//添加元素
c.add(1);
c.add(2);
c.add(2);
c.add(3);
c.add(4);
c.add(4);
//迭代集合
//创建迭代器
Iterator it = c.iterator();
//开始迭代
while (it.hasNext()){
//存进去的是什么类型,取出来的还是什么类型
Object obj = it.next();
if(obj instanceof Integer){
System.out.println("Integer类型");
}
//只不过在输出的时候会转换成字符串,因为这里println会调用toString()方法
System.out.println(obj);
/**
* Integer类型
* 1
* Integer类型
* 2
* Integer类型
* 2
* Integer类型
* 3
* Integer类型
* 4
* Integer类型
* 4
*/
}
//HashSet集合特点:无序不可重复
Collection c2 = new HashSet();
//无序:存进去和取出来的顺序不一定相同
//不可重复:存储100,不能再存储100
c2.add(100);
c2.add(200);
c2.add(300);
c2.add(80);
c2.add(500);
c2.add(360);
c2.add(100);
c2.add(100);
Iterator it2 = c2.iterator();
while (it2.hasNext()){
System.out.println(it2.next());
/**
* 80
* 100
* 500
* 200
* 360
* 300
*/
}
}
}
8、集合结构只要发生改变,迭代器必须重新获取
package com.javase.collection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/**
* 关于集合元素的remove
* 集合就像快照一样,当集合结构发生改变时,必须重新获取迭代器,否则调用next()方法:java.util.ConcurrentModificationException
*/
public class CollectionTest06 {
public static void main(String[] args) {
//创建集合
Collection c = new ArrayList();
/**
* 注意:此时获取的迭代器,指向的是集合中没有元素状态下的迭代器
* 一定要注意:集合结构只要发生改变,迭代器必须重新获取
* 当集合结构发生改变,迭代器没有重新获取时,调用next()方法:java.util.ConcurrentModificationException
*/
Iterator it = c.iterator();
//添加元素
c.add(1); //Integer类型
c.add(2);
c.add(3);
//循环集合
// Iterator it = c.iterator();
while (it.hasNext()){
//编写代码时next()方法返回值类型必须是Object
Object obj = it.next();
System.out.println(obj);
}
}
}
9、ArrayList实现迭代器源码

三、Collection接口中常用实例方法
集合中的元素对象一定要重写equals方法
在Java中,Collection接口是Java集合框架的根接口之一,它定义了一组通用的方法,可以用于操作和管理集合对象。
1、Collection接口中存放的元素
没有使用“泛型”之前,Collection中可以存储Object的所有子类型
使用了“泛型”之后,Collection中只能存储某个具体的类型
2、boolean add(E element):将指定元素添加到集合末尾
Collection collection = new ArrayList();
collection.add(100); //自动装箱,实际上是放进去了一个Integer类型的对象的引用
collection.add(3.14); //自动装箱
System.out.println(collection.add(new Object())); //true
//List集合特点:有序可重复
collection.add(true); //自动装箱
System.out.println(collection.add(true)); // true 自动装箱
3、int size():返回集合中的元素个数
//获取集合中元素的个数
System.out.println("集合中元素的个数:" + collection.size()); //集合中元素的个数:5
4、void clear():从集合中移除所有元素
//清空集合
collection.clear();
System.out.println("集合中元素的个数:" + collection.size()); //集合中元素的个数:0
5、boolean contains(Object element):判断集合是否包含指定元素(element),包含返回true,不包含返回false
//再向集合中添加元素
collection.add("hello"); //“hello”对象的内存地址放到了集合中
collection.add("world");
//判断集合中是否包含“hello”
boolean flag = collection.contains("hello");
System.out.println(flag); //true
System.out.println(collection.contains("jzq")); //false
5.1、contains原理解析
contains方法底层通过遍历集合中元素,调用equals方法将集合中元素和目标元素进行对比
若equals方法返回true,则表示包含这个元素
若equals方法返回false,则表示不包含这个元素
源码分析

案例一:String类已经重写了equals方法,比较内容
package com.javase.collection;
import java.util.ArrayList;
import java.util.Collection;
/**
* 深入Collection集合中contains方法;
* boolean contains(Object element):判断集合是否包含指定元素(element),包含返回true,不包含返回false
*
* contains方法是用来判断集合中是否包含某个元素的方法
* 那么它在底层是如何判断是否包含某个元素的尼?
* contains方法底层通过遍历集合中元素,调用equals方法将集合中元素和目标元素进行对比
* 若equals方法返回true,则表示包含这个元素
* 若equals方法返回false,则表示不包含这个元素
*/
public class CollectionTest04 {
public static void main(String[] args) {
//创建集合对象
Collection c = new ArrayList();
//向集合中添加元素
String s1 = new String("abc");
c.add(s1);
String s2 = new String("def");
c.add(s2);
//集合中元素的个数:
System.out.println("集合中元素的个数:" + c.size()); //2
String x = new String("abc");
System.out.println(c.contains(x)); //true
}
}

案例二:未重写equals方法,比较内存地址
package com.javase.collection;
import java.util.ArrayList;
/**
* 测试contains方法
*/
public class CollectionTest05 {
public static void main(String[] args) {
//创建集合对象
ArrayList arrayList = new ArrayList();
//创建用户对象
User u1 = new User("jzq");
User u2 = new User("jzq");
//加入集合
arrayList.add(u1);
//判断集合中是否包含u2
//没有重写equals方法之前,这个结果是false
//System.out.println(arrayList.contains(u2)); //false
//重写equals方法之后,这个结果是true
System.out.println(arrayList.contains(u2)); //true
//举个例子:因为Integer类重写了equals方法,比较内容
Integer x = new Integer(10000);
arrayList.add(x);
Integer y = new Integer(10000);
System.out.println(arrayList.contains(y)); //true
}
}
class User{
private String name;
public User(){}
public User(String name){
this.name = name;
}
public boolean equals(Object obj){
if(null == obj || !(obj instanceof User)){
return false;
}
if (this == obj){
return true;
}
User u = (User) obj;
//比较内容,如果名字一样则返回true(比较内容)
return this.name.equals(u.name);
}
}
6、boolean remove(Object element):从集合中移除指定的第一个元素
移除集合中某个值的第一个匹配项
System.out.println("集合中元素的个数:" + collection.size()); //2
//删除集合中指定的元素
collection.remove("hello");
System.out.println("集合中元素的个数:" + collection.size()); //1
6.1、remove原理解析
源码分析

案例:String类已经重写了equals方法,比较内容,所以删除s2是将s1删除
package com.javase.collection;
import java.util.ArrayList;
import java.util.Collection;
public class CollectionTest06 {
public static void main(String[] args) {
//创建集合对象
Collection c = new ArrayList();
//创建字符串对象
String s1 = new String("jzq");
//加入集合
c.add(s1);
//创建新的字符串对象
String s2 = new String("jzq");
//删除s2
c.remove(s2);
//集合中元素个数
System.out.println(c.size()); //0
List<? super String> list = new ArrayList<>();
list.add("jzq");
list.add("jzq");
System.out.println(list.size()); //2
list.remove("jzq");
System.out.println(list.size()); //1
}
}
7、boolean isEmpty():判断集合是否为空,为空返回true,不为空返回false
源码:

//判断集合是否为空(集合中是否存在元素)
System.out.println(collection.isEmpty()); //false
//清空
collection.clear();
System.out.println(collection.isEmpty()); //true
8、Object[] toArray():将集合转换为一个数组
collection.add(1);
collection.add(2);
collection.add("jzq");
collection.add(new Student());
//转换为数组
//编译报错:toArray方法返回值类型为Object[] 一维数组,则必须使用Object[]类型声明,不能使用其子类型
//Integer[] objs = collection.toArray();
Object[] objects = collection.toArray();
System.out.println(Arrays.toString(objects)); //[1, 2, jzq, com.javase.collection.Student@b4c966a]
四、List接口中特有常用实例方法
在Java中,List接口是一种有序的集合,允许重复元素。它扩展了Collection接口,并添加了一些特定于列表操作的方法。
1、void add(int index, E element):在指定索引位置插入指定元素,index是索引(使用较少)
//创建集合
List list = new ArrayList();
//添加元素
list.add("A");
list.add("B");
list.add("C");
list.add("D");
//void add(int index, E element):在指定索引位置插入指定元素
//这个方法使用不多,因为对于ArrayList集合来说效率较低,ArrayList底层是数组,涉及到元素位移问题
list.add(1,"KING");
//迭代集合
Iterator it = list.iterator();
while (it.hasNext()){
Object obj = it.next();
System.out.println(obj.toString()); // A KING B C D
}
2、E get(int index):返回指定索引位置的元素
//E get(int index):返回指定索引位置的元素
Object firstElement = list.get(0);
System.out.println(firstElement); //A
3、int indexOf(Object element):返回指定元素在列表中首次出现的索引
//int indexOf(Object element):返回指定元素在列表中首次出现的索引
int index = list.indexOf("KING");
System.out.println(index); //1
4、int lastIndexOf(Object element):返回指定元素在列表中最后一次出现的索引
//int lastIndexOf(Object element):返回指定元素在列表中最后一次出现的索引
int index1 = list.lastIndexOf("D");
System.out.println(index1); //4
5、E remove(int index):移除指定索引位置的元素,并将删除的元素返回
//E remove(int index):移除指定索引位置的元素
Object s = list.remove(0);
System.out.println(s); //A
System.out.println(list.size()); //4
System.out.println(list); //[KING, B, C, D]
6、E set(int index, E element):将指定索引位置的元素替换为新元素,并将原来位置处的元素返回
//E set(int index, E element):将指定索引位置的元素替换为新元素
Object obj = list.set(2,"SOFT");
System.out.println(obj); //C
System.out.println(list); //[KING, B, SOFT, D]
7、List集合特有的遍历集合方式(采用get方法)
//除了迭代器之外另外遍历集合的方式:采用索引遍历
for (int i = 0; i < list.size(); i++) {
Object ele = list.get(i);
System.out.println(ele);
}
8、遍历List集合的三种方式
package com.javase.collection.forEach增强for循环;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* 集合使用foreach
*/
public class ForEachTest02 <T>{
public static void main(String[] args) {
//创建list集合
List<String> list = new ArrayList<>();
ForEachTest02<String> f = new ForEachTest02<>();
//添加元素
list.add("Hello");
list.add("world");
list.add("kitty");
//遍历,采用迭代器方式
f.demo1(list);
System.out.println("===================");
//采用get索引方式
f.demo2(list);
System.out.println("===================");
//采用foreach方式
f.demo3(list);
}
//第三种方式:iterator迭代器
public void demo1(List<T> list){
Iterator<T> it = list.iterator();
while (it.hasNext()){
T obj = it.next();
System.out.println(obj);
}
}
//第二种方式:for循环
public void demo2(List<T> list){
for (int i = 0; i < list.size(); i++) {
T obj = list.get(i); //list集合特有的方法
System.out.println(obj);
}
}
//第一种方式:foreach循环
public void demo3(List<T> list){
for (T element:
list) {
System.out.println(element);
}
}
}
五、ArrayList实现类
在Java中,ArrayList是一种实现了List接口的动态数组,它提供了一种便捷的方式来操作元素集合。
1、ArrayList的特点
1.1、动态数组
ArrayList内部使用数组来存储元素,它可以根据需要动态增长或缩小数组的大小。当添加元素超过当前数组的容量时,ArrayList会自动扩容,通常以当前容量的一定比例进行扩展。
1.2、有序集合
ArrayList中的元素按照添加的顺序进行存储,它保持元素的插入顺序,并允许通过索引访问元素。
1.3、允许重复元素
ArrayList可以存储重复的元素,不会对元素的唯一性进行限制。
1.4、随机访问
ArrayList支持通过索引快速访问元素,由于底层使用数组存储,因此可以根据索引在常数时间内访问特定位置的元素。
1.5、插入和删除效率较低
由于ArrayList是基于数组实现的,当需要在中间位置插入或删除元素时,需要移动后续元素来填补空缺或者重新分配数组的内存空间,因此插入和删除操作的效率较低。
1.6、不适合频繁的插入和删除操作
由于插入和删除操作的效率较低,当需要频繁进行插入和删除操作时,LinkedList可能是更好的选择。
1.7、非线程安全
ArrayList不是线程安全的,如果在多线程环境下使用ArrayList,需要自行考虑线程同步的问题。
总的来说,ArrayList适用于需要频繁随机访问元素、根据索引进行操作的场景,对于插入和删除操作不太频繁的情况下,它提供了高效的操作方式
1.8、ArrayList集合初始化容量为10(底层先创建了一个长度为0的数组,当添加第一个元素的时候,初始化容量为10)
在Java中,ArrayList是通过数组实现的动态数组,其源码中有一个常量 DEFAULTCAPACITY

最低0.47元/天 解锁文章
1043

被折叠的 条评论
为什么被折叠?



