什么是集合
- Java是一门面向对象的语言.
- 为了方便操作多个对象,那么我们就得把这多个对象存储起来
- 想要存储多个对象(变量),我们就需要一个容器
- 集合就是一个放数据的容器(集合类存放的都是对象的引用,而非对象本身)
Collection的由来:
-
集合可以存储多个元素,但我们对多个元素也有不同的需求
- 多个元素,元素之间不能重复的
- 多个元素,元素按某种规则排序的
- 针对不同的需求:java就提供了很多集合类,多个集合类的数据结构不同。但是,结构不重要,重要的是能够存储东西,能够判断,获取
- 把集合共性的内容不断往上提取,最终形成集合的继承体系---->Collection
Collection的继承结构
常见问题:
数组和集合的区别
1:长度的区别
- 数组的长度固定
- 集合的长度可变
2:内容不容
- 数组存储的是同一种类型的元素
- 集合可以存储不同类型的元素(但是一般我们不这样干..)
3:元素的数据类型
- 数组可以存储基本数据类型,也可以存储引用类型
- 集合只能存储引用类型(你存储的是简单的int,它会自动装箱成Integer)
什么时候使用集合,什么时候使用数组?
使用数组的缺陷:
- 数组长度设置过小就造成溢出
- 如果数组的长度设置过大,就造成内存空间浪费(因为数组的长度是固定的)
为什么还要使用数组呢 ?
- 集合的底层都是通过数组来实现的
2.数组的效率更高.例如:IO流 byte[] arr=new byte[1024];就是使用的数组
怎么选择集合?
需要唯一吗?
需要:Set
需要制定顺序吗?
需要:TreeSet
不需要:HashSet
但是想要一个和存储一致的顺序(有序):LinkedHashSet
不需要:List
需要频繁增加或者删除元素吗?
需要:LinkedList
不需要:ArrayList
前缀名就是该集合的数据结构.后缀名就是该集合所属的体系
看到array:就要想到数组,就要想到查询快,有角标
看到link:就要想到链表,就要想到增删快,就要想到 add get remove+first last 方法
看到hash:就要想到哈希表,就要想到唯一性,就要想到元素需要覆盖hashcode方法和equals方法
看到tree:就要想到二叉树,就要想到排序,就要想到两个接口Comparable和Comparator
Collection的常见方法
数组转换成集合
集合转换成数组
Collection的主要子类List和Set
List常见方法:
List:有顺序的collection,并且可以包含重复元素。
├ArrayList
- 数组结构,查询元素快,添加慢(一般情况下),线程不安全,效率高
└Vector
- 数组结构,查询元素快,线程安全.效率比ArrayList低
- 现在几乎不适用
├LinkedList
- 链表结构,添加元素快,查询慢,线程不安全,效率高
细节说明:
LinkedList不同于前面两种List,它不是基于数组的,所以不受数组性能的限制。
他的每一个节点(Node)都包含了三方面的内容:
1.节点本身的数据: E item;
2.上一个节点的信息:Node<E> prev;
3.下一个节点的信息:Node<E> next;
所以当对LinkedList做添加,删除动作的时候就不用像基于数组的ArrayList一样,必须进行大量的数据移动。只要更改nextNode的相关信息就可以实现了,这是LinkedList的优势。 所以LinkedList集合添加数组效率高
LinkedList的常用方法:
注意事项:LinkedList在内存中不是连续的,ArrayList在内存中是连续的.
List集合的遍历方式:
方式一:迭代器模式,假设集合名为(al)
Iterator<String> iterator = al.iterator();
while (iterator.hasNext()) {
String s = iterator.next();
System.out.println(s);
}
扩展:使用ListIterator方式进行遍历,可以在遍历的过程中对集合进行增删改查,只有list有这种方式,使用ListIterator方式还能进行反向遍历
方式二:增强for
for (String s : al) {
System.out.println(s);
}
方式三:普通for (List特有)
for (int i = 0; i <al.size(); i++) {
System.out.println(al.get(i));
}
List总结:
- 基于Array的List(Vector,ArrayList)适合查询,而LinkedList 适合添加,删除操作
- 所有的List中可以有null元素,例如[ tom,null,1 ]
- 所有的List中可以有相同的元素,例如Vector中可以有 [ tom,koo,too,koo ]
- 所有的List中只能容纳单个不同类型的对象组成的表(单列集合),而不是Key-Value键值对。例如:[ tom,1,c ]
- List是有序的Collection,使用此接口能够精确的控制每个元素插入的位置。用户能够使用索引(元素在List中的位置,类似于数组下 >标)来访问List中的元素,这类似于Java的数组。
- ArrayList和Vector的区别:ArrayList是非线程安全的,效率高;Vector是基于线程安全的,效率低
- LinkedList:底层基于链表实现,链表内存是散乱的,每一个元素存储本身内存地址的同时还存储下一个元素的地址。链表增删快,查找慢
- List接口有三个常用实现类:LinkedList,ArrayList,Vector
Set :不包含重复元素的Collection。
├HashSet (数据结构是哈希表)
HashSet 怎么确认唯一?
首先判断的是两个元素的哈希值确认元素是否相同,如果相同,再判断两个对象的内容是否相同
判断哈希值是否相同,即是判断hashCode方法,判断内容是否相同,即是判断equals方法
注意:如果哈希值不同,是不需要判断equals方法的
如果两个哈希值相同会造成哈希冲突,一般情况下,哈希值都是不会冲突的(这里不做详细介绍)
记住:如果元素要存储到HashSet集合中,必须覆盖hashCode和equals方法.
一般情况下,如果定义的类会产生很多对象,比如人,学生,书,通常都是覆盖hashCode和equals方法.建立对象是否相同的依据.
└LinkedhashSet (HashSet的一个子类,一个链表)
LinkedhashSet可以保证元素的有序!
└TreesSet (排序,不重复,无索引)
Set的遍历方式:
方式一:迭代器
Set<String> set = new HashSet<String>();
Iterator<String> it = set.iterator();
while (it.hasNext()) {
String str = it.next();
System.out.println(str);
}
方式二:增强for
for (String str : set) {
System.out.println(str);
}
Set知识点讲解
- 虽然Set同List都实现了Collection接口,但是他们的实现方式却大不一样。List基本上都是以Array为基础。但是Set则是在 HashMap的基础上来实现的,这个就是Set和List的根本区别。HashSet的存储方式是把HashMap中的Key作为Set的对应存储项。
- 这个也是为什么在Set中不能像在List中一样有重复的项的根本原因,因为HashMap的key是不能有重复的。
- HashSet中的元素是不能重复的,如果使用add(Object obj)方法添加已经存在的对象,则会覆盖前面的对象
- HashSet实现的基础是Map(HashMap)
- HashSet是一种不包含重复的元素的无序Collection。
- 元素无放入顺序,元素不可重复(注意:元素虽然无放入顺序,但是元素在set中的位置是有该元素的HashCode决定的,其位置其实是固定的)
集合排序
方式一(让Bean类实现Comparable接口重写compareTo方法) 自然排序
返回值 0 , 不存
正数 , 右边
负数 , 左边
方式二(自定义一个类实现Comparator接口重写compare方法,通过构造方法传入自定义类的对象)比较器排序
比如:String ,Integer 对象 ,实现特殊的排序需求, 需要传递比较器的子类对象 .