Java--集合(理论)上
目录
一、collection
collection常用方法
1.List(可以存在重复元素)
迭代器
迭代器的概念
注意事项
例子
1.ArrayList
特点
2.LinkedLIst
特点
3.Vector
特点
2.Set(无重复元素)
1.HashSet
特点
2.Linkedhashset(应用不多)
特点
3.TreeSet
特点
小问题
⭐面试题⭐
== 和 equals 方法的区别?
1. 基本概念
==
equals
2. 分场景分析
基本数据类型
引用类型
在Java中,集合主要分为两大体系:Collection&Map
集合这里经常和泛型一块用,在这里:Java详析--泛型-CSDN博客 + Java详解--泛型_java 抽象类范型属性-CSDN博客
泛型就是在集合中指定存储的数据类型,而且只能存储这种类型,在List<类型>必须要指定, ArrayList<>可以指定也可以不指定。注意:基本数据类不能作为泛型(但是基本类型的包装类可以用。)。
一、collection
其中collection在Java中的应用极为常见,大致分支图为:
collection常用方法
添加相关的方法
add(E e) 确保此 collection 包含指定的元素(可选操作)。
addAll(Collection<? extends E> c)
将指定 collection 中的所有元素都添加到此 collection 中(可选操作)。
删除相关的方法
clear() 移除此 collection 中的所有元素(可选操作)。
remove(Object o) 从此 collection 中移除指定元素的单个实例,如果存在的话(可选操作)。
removeAll(Collection<?> c) 移除此 collection 中那些也包含在指定 collection 中的所有元素(可选操作)。
判断相关的方法
contains(Object o) 如果此 collection 包含指定的元素,则返回 true。
containsAll(Collection<?> c) 如果此 collection 包含指定 collection 中的所有元素,则返回 true。
isEmpty() 如果此 collection 不包含元素,则返回 true。
数组的转换相关方法
toArray() 返回包含此 collection 中所有元素的数组。
1.List(可以存在重复元素)
通过使用集合,ArrayList(应用最多)、Vector、LinkedList等三个继承list的类能够实现了动态扩容。
java.util.Collection└── java.util.List├── java.util.ArrayList├── java.util.Vector└── java.util.LinkedList
List集合的特点(list底层实现本质就是数组):
- 有序集合
- 元素可以重复(有索引,list本质靠索引区分而不是内容本身)
- 长度可变
- 底层实现为数组
迭代器
对于list的使用,collection常用使用方法几乎涵盖了,在此补充一个迭代器的概念:
Iterator<E> | iterator() 返回在此 collection 的元素上进行迭代的迭代器。 |
迭代器的概念
迭代器(Iterator)是一种设计模式,在 Java 中是一个对象,它提供了一种统一的方式来访问集合中的元素,而不需要关心集合的具体实现细节。迭代器的主要作用是遍历集合中的元素,同时可以在遍历过程中进行一些操作,如删除元素等。
Java 中的迭代器主要有两种:Iterator
和 ListIterator
。
Iterator
:是 Java 集合框架中最基本的迭代器接口,它可以用于遍历各种集合,如List
、Set
等。Iterator
提供了三个主要方法:
hasNext()
:判断集合中是否还有下一个元素。next()
:返回集合中的下一个元素,并将迭代器的位置向后移动一位。remove()
:删除迭代器最后返回的元素。
ListIterator
:是Iterator
的子接口,专门用于遍历List
集合。ListIterator
除了继承了Iterator
的方法外,还提供了一些额外的方法,如:
hasPrevious()
:判断集合中是否还有上一个元素。previous()
:返回集合中的上一个元素,并将迭代器的位置向前移动一位。add(E e)
:在当前迭代位置插入一个元素。set(E e)
:用指定元素替换迭代器最后返回的元素。
注意事项
在使用迭代器遍历集合时,如果需要修改集合的结构(如添加、删除元素),应该使用迭代器提供的方法(如 ListIterator
的 add()
和 remove()
方法),而不是直接调用集合的方法(如 List
的 add()
和 remove()
方法),否则可能会引发 ConcurrentModificationException
异常。
例子
1.通过ListIterator的方式遍历:
ListIterator listIterator = list.listIterator();
while(listIterator.hasNext()){//获得迭代的元素String str = (String) listIterator.next();if("刘唐".equals(str)){//我们不能在一边遍历的时候一边操作集合,这样有多线程的并发问题//list.add("白胜");//迭代器可以给我们提供了一个add方法让我们避免并发问题,但是添加的时候本次遍历不生效listIterator.add("白胜"); //直接使用list的add方法就会造成count问题}System.out.println(str);}
System.out.println(list);
2.for循环来动态的遍历List集合
System.out.println("---------------分割线 for循环遍历list-----------------------");
//int size = list.size();
//for循环对list的变量, 我们可以使用动态获得集合的长度的方式来遍历
for (int i = 0; i < list.size(); i++) {//根据索引来获得对应的元素String str = (String) list.get(i);if("刘唐".equals(str)){list.add("阮小五");}System.out.println(str);
}
简单场景下,for循环的遍历方式完全能够替代迭代器。
1.ArrayList
ArrayList是List中应用最多的实现类。
特点
ArrayList的底层是数组的原理。
ArrayList中的元素是可以重复
是有序的集合,长度不固定。
不是线程安全的(适用于追求效率但是对线程安全度要求不那么高)。
效率高、性能好。
2.LinkedLIst
特点
Linked也不是线程安全的。
- 底层结构是链表实现(对增删改更加友好)
- 适合做增删改的业务场景
- 线程不安全
- 有序集合但是更适合增删改
3.Vector
特点
Vector底层也是数组。
线程安全,支持多线程并发访问
可以存储任意类型对象,包括null
自定扩容,扩容机制是增量为当前容量的一半
2.Set(无重复元素)
Set同样是是Collection的子接口,具备无序性;而且Set是个接口,不能直接创建对象,需要实现类来创建对象
Set的实现类是HashSet(用的最多),linkedhashset, Treeset
1.HashSet
特点
1.元素唯一性
2.无序性
3.允许null存在一个(本质还是元素唯一性)
4.不是线程安全(效率高)
5,底层实现是数据结构是哈希表(哈希表依赖的两个方法:hashcode()和equals()方法)
(一般规则:对象的equals是true的话,hashcode需要相同,但是hashcode相同的对象不一定equals相同,这就是所谓的冲突现象,但是有不同的解决方法。你的hashCode()方法设计的好就会减少冲突。)
2.Linkedhashset(应用不多)
特点
1.元素唯一性
2.有序的
3.允许null存在一个
4.不是线程安全(效率高)
5,底层数据结构由链表和哈希表组成。
LinkedHashSet和HashSet来对比本质就是多了一个顺序。
3.TreeSet
类如果要实现比较的规则都会实现Comparable接口(所以创建几个类想填入TreeSet就要先行实现Comparable接口)。
特点
1.元素唯一性
2.可自定义排序的(两种 Comparable接口 自己定义比较类实现Comparator比较器接口)
3.不允许null存在
4.不是线程安全
5,treeset集合中的包装类都必须实现Comparable接口。
6,底层数据结构是红黑树。(是一种自平衡的二叉树)
小问题
工具类Arrays
数组的工具类,这里的方法都是静态的
1.把数组转换成字符串
2.对任意数组排序
3.对任意的数组做二分法的查找
4.把数组转换成List
工具类Collections
⭐面试题⭐
问:Collection和Collections的区别:
前者是集合的接口
后者操作集合的工具类
== 和 equals 方法的区别?
1. 基本概念
==
==
是一个比较运算符,它的作用取决于操作数的类型:
- 当操作数是基本数据类型时,
==
比较的是它们的值是否相等。- 当操作数是引用类型时,
==
比较的是两个引用是否指向内存中的同一个对象,即比较它们的内存地址是否相同。
equals
equals
是Object
类中定义的一个方法,所有的类都继承自Object
类,因此所有的对象都可以调用equals
方法。在Object
类中,equals
方法的默认实现和==
是一样的,也是比较两个对象的内存地址是否相同。不过,很多类(如String
、Integer
等)会重写equals
方法,用于比较对象的内容是否相等。2. 分场景分析
基本数据类型
基本数据类型(如
int
、double
、boolean
等)只能使用==
进行比较,不能使用equals
方法,因为基本数据类型不是对象,没有方法。引用类型
引用类型既可以使用
==
也可以使用equals
方法进行比较。
- 使用
==
:比较的是两个引用是否指向同一个对象,即它们的内存地址是否相同。public class ReferenceComparison {public static void main(String[] args) {String str1 = new String("hello");String str2 = new String("hello");// 使用 == 比较引用类型的内存地址boolean result1 = str1 == str2; System.out.println(result1); // 输出: falseString str3 = str1;boolean result2 = str1 == str3; System.out.println(result2); // 输出: true} }/* 在这个例子中,str1 和 str2 虽然内容相同, 但它们是通过 new 关键字创建的两个不同的对象, 内存地址不同,所以 str1 == str2 的结果为 false。 而 str3 直接引用了 str1,它们指向同一个对象, 所以 str1 == str3 的结果为 true。*/
使用
equals
:在Object
类中,equals
方法的默认实现和==
一样,比较的是对象的内存地址。但很多类会重写equals
方法,用于比较对象的内容是否相等。public class EqualsComparison {public static void main(String[] args) {String str1 = new String("hello");String str2 = new String("hello");// 使用 equals 比较引用类型的内容boolean result = str1.equals(str2); System.out.println(result); // 输出: true} }/* 在这个例子中,String 类重写了 equals 方法,用于比较字符串的内容是否相等。 虽然 str1 和 str2 是两个不同的对象, 但它们的内容相同,所以 str1.equals(str2) 的结果为 true。*/
综上所述,在比较基本数据类型时,只能使用
==
;在比较引用类型时,如果要比较对象的内存地址,使用==
;如果要比较对象的内容,使用重写了equals
方法的对象调用该方法。