文章目录
概述
- 一方面,面向对象语言对事物的体现都是以对象的形式,为了方便对多个对象的操作,就要对对象进行存储。另一方面,使用Array存储对象方面具有 一 些 弊 端 \textcolor{Red}{一些弊端} 一些弊端,而Java集合就像一种容器,可以 动 态 地 \textcolor{Blue}{动态地} 动态地把多个对象的引用放入容器中。
- 数组在内存存储方面的特点:
- 数组初始化以后,长度就确定了。
- 数组声明的类型,就决定了进行元素初始化时的类型
- 数组在存储数据方面的弊端:
- 数组初始化以后,长度就不可变了,不便于扩展
- 数组中提供的属性和方法少,不便于进行添加、删除、插入等操作,且效率不高。同时无法直接获取存储元素的个数
- 数组存储的数据是有序的、可以重复的。---->存储数据的特点单一
- Java集合类可以用于存储数量不等的多个 对 象 \textcolor{Red}{对象} 对象,还可用于保存具有映射关系的关联数组。
Java集合可分为Collection和 Map 两种体系
-
C
o
l
l
e
c
t
i
o
n
接
口
:
\textcolor{Red}{Collection接口:}
Collection接口:单列数据,定义了存取一组对象的方法的集合
-
L
i
s
t
:
\textcolor{Red}{List:}
List:元素有序、可重复的集合(“动态”数组)
- ArrayList
- LinkedList
- Vector
-
S
e
t
:
\textcolor{Red}{Set:}
Set:元素无序、不可重复的集合 —> 高中讲的“集合”
- HashSet
- LinkedHashSet
- TreeSet
-
L
i
s
t
:
\textcolor{Red}{List:}
List:元素有序、可重复的集合(“动态”数组)
-
M
a
p
接
口
:
\textcolor{Red}{Map接口:}
Map接口:双列数据,保存具有映射关系“key-value对”的集合 —> 高中“函数” y = f{x}
- HashMap
- LinkedHashMap
- TreeMap
- Hashtable
- Properties
Collection接口方法
- 添加
- a d d ( O b j e c t \textcolor{Red}{add(Object} add(Object o b j ) \textcolor{Red}{obj)} obj)
- a d d A l l ( C o l l e c t i o n \textcolor{Red}{addAll(Collection} addAll(Collection c o l l ) \textcolor{Red}{coll)} coll)
- 获取有效元素的个数
- i n t \textcolor{Red}{int} int s i z e ( ) \textcolor{Red}{size()} size()
- 清空集合
- v o i d \textcolor{Red}{void} void c l e a r ( ) \textcolor{Red}{clear()} clear()
- 是否是空集合
- b o o l e a n \textcolor{Red}{boolean} boolean i s E m p t y ( ) \textcolor{Red}{isEmpty()} isEmpty()
- 是否包含某个元素
- b o o l e a n \textcolor{Red}{boolean} boolean c o n t a i n s ( O b j e c t \textcolor{Red}{contains(Object} contains(Object o b j ) : \textcolor{Red}{obj):} obj):是通过元素的equals方法来判断是否是同一个对象
- b o o l e a n \textcolor{Red}{boolean} boolean c o n t a i n s A l l ( C o l l e c t i o n \textcolor{Red}{containsAll(Collection} containsAll(Collection c ) : \textcolor{Red}{c):} c):也是调用元素的equals方法来比较的。拿两个集合的元素挨个比较。
- 删除
- b o o l e a n \textcolor{Red}{boolean} boolean r e m o v e ( O b j e c t \textcolor{Red}{remove(Object} remove(Object o b j ) : \textcolor{Red}{obj):} obj):通过元素的equals方法判断是否是要删除的那个元素。只会删除找到的第一个元素
- b o o l e a n \textcolor{Red}{boolean} boolean r e m o v e A l l ( C o l l e c t i o n \textcolor{Red}{removeAll(Collection} removeAll(Collection c o l l ) : \textcolor{Red}{coll):} coll):取当前集合的差集
- 取两个集合的交集
- b o o l e a n \textcolor{Red}{boolean} boolean r e t a i n A l l ( C o l l e c t i o n \textcolor{Red}{retainAll(Collection} retainAll(Collection c ) : \textcolor{Red}{c):} c):把交集的结果存在当前集合中,不影响c
- 集合是否相等
- b o o l e a n \textcolor{Red}{boolean} boolean e q u a l s ( O b j e c t \textcolor{Red}{equals(Object} equals(Object o b j ) \textcolor{Red}{obj)} obj)
- 转成对象数组
- O b j e c t [ \textcolor{Red}{Object[} Object[ ] \textcolor{Red}{]} ] t o A r r a y ( ) \textcolor{Red}{toArray()} toArray()
- 获取集合对象的哈希值
- h a s h C o d e ( ) \textcolor{Red}{hashCode()} hashCode()
- 遍历
- i t e r a t o r ( ) : \textcolor{Red}{iterator():} iterator():返回迭代器对象,用于集合遍历
使用lterator接口遍历集合元素
- lterator对象称为迭代器(设计模式的一种),主要用于遍历Collection集合中的元素。
- G O F 给 迭 代 器 模 式 的 定 义 为 : 提 供 一 种 方 法 访 问 一 个 容 器 ( c o n t a i n e r ) 对 象 中 各 个 元 素 , 而 又 不 需 暴 露 该 对 象 的 内 部 细 节 。 姓 代 器 模 式 , 就 是 为 容 器 而 生 。 \textcolor{Red}{GOF给迭代器模式的定义为:提供一种方法访问一个容器(container)对象中各个元素,而又不需暴露该对象的内部细节。姓代器模式,就是为容器而生。} GOF给迭代器模式的定义为:提供一种方法访问一个容器(container)对象中各个元素,而又不需暴露该对象的内部细节。姓代器模式,就是为容器而生。类似于“公交车上的售票员”、“火车上的乘务员”、“空姐”。
- Collection接口继承了java.lang.lterable接口,该接口有一个iterator()方法,那么所有实现了Collection接口的集合类都有一个iterator()方法,用以返回一个实现了lterator接口的对象。
- l t e r a t o r 仅 用 于 遍 历 集 合 \textcolor{Blue}{lterator仅用于遍历集合} lterator仅用于遍历集合,lterator木身并不提供承装对象的能力。如果需要创建lterator 对象,则必须有一个被迭代的集合。
- 集 合 对 象 每 次 调 用 i t e r a t o r ( ) 方 法 都 得 到 一 个 全 新 的 迭 代 器 对 象 \textcolor{Blue}{集合对象每次调用iterator()方法都得到一个全新的迭代器对象} 集合对象每次调用iterator()方法都得到一个全新的迭代器对象,默认游标都在集合的第一个元素之前。
注 意 : \textcolor{Red}{注意:} 注意:
- lterator可以删除集合的元素,但是是遍历过程中通过迭代器对象的remove方法,不是集合对象的remove方法。
- 如 果 还 未 调 用 n e x t ( ) 或 在 上 一 次 调 用 n e x t 方 法 之 后 已 经 调 用 了 r e m o v e 方 法 , 再 调 用 r e m o v e 都 会 报 I l l e g a l S t a t e E x c e p t i o n 。 \textcolor{Red}{如果还未调用next()或在上一次调用next方法之后已经调用了remove方法,再调用remove都会报IllegalStateException。} 如果还未调用next()或在上一次调用next方法之后已经调用了remove方法,再调用remove都会报IllegalStateException。
使用foreach循环遍历集合元素(JDK5.0)
- Java 5.0提供了foreach循环迭代访问Collection和数组。
- 遍历操作不需获取collection或数;。/;‘
”组的长度,无需使用索引访问元素。 - 遍 历 集 合 的 底 层 调 用 I t e r a t o r 完 成 操 作 。 \textcolor{Blue}{遍历集合的底层调用Iterator完成操作。} 遍历集合的底层调用Iterator完成操作。
- foreach还可以用来遍历数组。
面试题:ArrayList、LinkedList、Vector三者异同
同:三个类都是实现了LIst接口,存储数据的特点相同:存储有序的、可重复的数据
不同:
- ArrayList:作为List接口的主要实现类;线程不安全,效率高;底层使用Object[ ] elementData存储
- LinkedList:对于频繁的插入、删除操作,使用此类效率比ArrayList高;底层使用双向链表存储
- Vector:作为List接口的古老实现类;线程是安全的,效率低;底层使用Object[ ] elementData存储
ArrayList的源码分析:
jdk7情况下
ArrayList list = new ArrayList();//底层创建了长度是10的object[ ]数组eLementData
list.add(123); //elementData[e] = new Integer(123);
…
list.add(11); //如果此次的添加导致底层elementData数组容量不够,则扩容。
默认情况下,扩容为原来的容量的1.5倍,同时需要将原有数组中的数据复制到新的数组中。
结
论
:
\textcolor{Red}{结论:}
结论:建议开发中使用带参的构造器: ArrayList list = new ArrayList(int capacity)
jdk8中ArrayList的变化:
ArrayList list = new ArrayList();//底层Object[ ] elementData初始化为{ },并没有创建长度为10的数组
list.add(123);//第一次调用add()时,底层才创建了长度为10的数组,并将数据123添加到elementData[0]中
…
后续添加和扩容操作与jdk7无异。
小结:jdk7中的ArrayList的对象的创建类似于单例的饿汉式,而jdk8中的ArrayList的对象的创建类似于单例的懒汉式,延迟了数组的创建,节省内存。
LinkedList的源码分析:
LinkedList list = new LinkedList(); 内部声明了Node类型的first和last属性,默认值为null
list.add(123); //将123封装到Node中,创建了Node对象
其中,Node定义为:体现了LinkedList的双向链表说法
private static class Node<E>{
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev,E element,Node<E> next){
this.item = element;
this.next = next;
this.prev = prev;
}
}
Vector的源码分析:jdk7和jdk8中通过Vector()构造器创建对象时,底层都创建了长度为10的数组。在扩容方面,默认扩容为原来数组的2倍。
代码实现:
import org.junit.Test;
import java.util.*;
/**
* @创建人 Hexin
* @创建时间 2022/12/1
* @描述
*/
public class CollectionTest {
/**
*@BelongsProject: JavaSenior
*@BelongsPackage: PACKAGE_NAME
*@Author: hexin
*@CreateTime: 2022-12-01 12:47
*@Description:
*@Version: 1.0
*
*/
@Test
public void test() {
Collection collection = new ArrayList();
//add(Object o):将元素e添加到集合collection中
collection.add("AA");
collection.add("BB");collection.add(123); //自动装箱
collection.add(new Date());
//size():获取添加元素的个数
System.out.println(collection.size());//4
//addAll():将collection1集合中的元素添加到当前集合中
Collection collection1 = new ArrayList();
collection1.add("CC");
collection1.add(456789);
collection.addAll(collection1);
System.out.println(collection.size());//6
System.out.println(collection);
//clear():清空集合元素
collection.clear();
//isEmpty():判断当前集合是否为空
System.out.println(collection.isEmpty());
collection.add(new String("WLM"));
collection.add(new Person("WLM",20));
//contains(Object o):判断当前集合中是否包含obj
//我们在判断时会调用obj对象所在类的equals()方法。
//向Collection接口的实现类的对象中添加数据obj时,要求obj所在类要重写equals().
boolean contains = collection.contains("CC");
System.out.println(contains);
System.out.println(collection.contains(new String("WLM"))); //比较的是内容
System.out.println(collection.contains(new Person("WLM",20)));
//containsAll(Collection collection1):判断collection1中的所有元素是否都存在于当前集合中。
Collection collection2 = Arrays.asList(new Person("WLM",20),new String("WLM"));
boolean b = collection.containsAll(collection2);
System.out.println(b);
}
@Test
public void test1() {
Collection collection = new ArrayList();
collection.add("AA");
collection.add("BB");
collection.add(123);
collection.add(new Date());
collection.add(new String("WLM"));
collection.add(new Person("WLM",20));
//remove(Object obj)
System.out.println(collection.remove(123));
//removeAll(Collection collection1):从当前集合中移除collection1中所有元素
Collection collection1 = Arrays.asList(123,"AA","CXY","11223");
collection.removeAll(collection1);
System.out.println(collection);
//retainAll(Collection collection1):
collection.retainAll(collection1);
System.out.println(collection);
//equals(Object obj):判断当前集合和形参集合元素是否完全相等
Collection collection2 = new ArrayList();
collection2.addAll(collection);
System.out.println(collection2.equals(collection));
}
@Test
public void test2() {
Collection collection = new ArrayList();
collection.add("AA");
collection.add("BB");
collection.add(123);
collection.add(new Date());
collection.add(new String("WLM"));
collection.add(new Person("WLM",20));
//hashCode
System.out.println(collection.hashCode());
//集合 ---> 数组:toArray()
Object array[] = collection.toArray();
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
//拓展:数组 ---> 集合:调用Arrays类静态方法asList()
List<String> strings = Arrays.asList(new String[]{"AA", "BB", "CC"});
System.out.println(strings);
//数组类型转换方式一:
List array1 = Arrays.asList(123,456);
System.out.println(array1);
//数组类型转换方式二:
List array2 = Arrays.asList(new Integer[]{1,2,3,4});
System.out.println(array2);
System.out.println("******************");
}
//iterator():返回Iterator接口的实例,用于遍历集合元素。放在IteratorTest.java中测试
@Test
public void test3(){
Collection collection = new ArrayList();
collection.add("AA");
collection.add("BB");
collection.add(123);
collection.add(new Date());
collection.add(new String("WLM"));
collection.add(new Person("WLM",20));
Iterator iterator = collection.iterator();
//方式一:
System.out.println(iterator.next());
System.out.println(iterator.next());
System.out.println(iterator.next());
System.out.println(iterator.next());
System.out.println(iterator.next());
System.out.println(iterator.next());
System.out.println(iterator.next());
//超出报异常
System.out.println(iterator.next());
//方式二:不推荐
for (int i = 0; i < collection.size(); i++) {
//next():① 指针下移 ② 将下移以后集合位置上的元素返回
System.out.println(iterator.next());
}
//方式三:推荐
//hashNext():判断是否还有下一个元素。
while(iterator.hasNext()) {
System.out.println(iterator.next());
}
}
@Test
public void test4() {
Collection collection = new ArrayList();
collection.add("AA");
collection.add("BB");
collection.add(123);
collection.add(new Date());
collection.add(new String("WLM"));
collection.add(new Person("WLM",20));
//删除集合中"WLM"数据
Iterator iterator = collection.iterator();
while(iterator.hasNext()){
Object object = iterator.next();
if(object.equals("WLM")){
iterator.remove();
}
}
iterator = collection.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
}
@Test
public void test5() {
Collection collection = new ArrayList();
collection.add("AA");
collection.add("BB");
collection.add(123);
collection.add(new Date());
collection.add(new String("WLM"));
collection.add(new Person("WLM",20));
//for(集合元素的类型 局部变量 :集合对象)
for(Object obj : collection){
System.out.println(obj);
}
Object array[] = collection.toArray();
//for(数组元素的类型 局部变量 :数组对象)
for(Object obj : array){
System.out.println(obj);
}
}
}
class Person{
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public Person() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
System.out.println("Person equals()......");
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age && Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
注:此文章为本人学习过程中的随手笔记,样式较为简陋,若有雷同,请见谅!