集合
集合的概念
-
集合是java中提供的一种容器,可以用来存储多个数据。
-
与数组的区别
- 数组的长度是固定的。集合的长度是可变的。
- 数组中可以存储基本数据类型值,也可以存储对象,而集合中只能存储对象
Collection 接口
- Collection是所有单列集合的父接口,因此在Collection中定义了单列集合(List和Set)通用的一些方法,这些方法可用于操作所有的单列集合。
Collection 中的使用方式
- 添加元素
a.add( );
- 删除元素
a.remove( );
- 查询元素
a.contains( );
- 交集(查询两个集合中相同的元素)
a1.retainAll(a2);
- 并集(把a1和a2集合中的元素合并到一起)
a1.addAll(a2);
- 判断是否为空的集合
boolean a1 = a2.isEmpty( );
- 获取集合中存储了几个元素
int a1 = a2.size( );
- 将集合转为数组
Object[ ] a1 = a2.toArray( );
- 删除a2在a1中相同的元素,并保留a1的不同元素
a1.retainAll(a2);
Iterator 迭代器
- 即Collection集合元素的通用获取方式。在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来,继续在判断,如果还有就再取出出来。一直把集合中的所有元素全部取出。这种取出方式专业术语称为迭代。
Collection 集合遍历
- 增强for(底层本质也是迭代器)
for(集合元素类型 变量名 : 集合名){
//变量名表示:集合中的元素
}
- 迭代器
Iterator<泛型名> 方法名 = 集合名.iterator();
while(方法名.hasNext()){
泛型名 变量名 = 方法名.next();
System.out.println(变量名);
}
Iterable接口 与 Iterator接口
- 对于集合类型来说,foreach循环其实就是使用Iterator迭代器来完成元素的遍历的。
- foreach循环的语法格式:
for(元素类型 元素名 : 数组名等){
//这里元素名就是一个临时变量,自己命名就可以
}
-
Iterable接口的抽象方法:
public Iterator iterator(): 获取对应的迭代器,用来遍历集合中的元素的。
数据结构
随着应用程序变得越来越复杂和数据越来越丰富,
几百万、几十亿甚至几百亿的数据就会出现,
而对这么大对数据进行搜索、插入或者排序等的操作就越来越慢,
数据结构就是用来解决这些问题的。
数据的逻辑结构指反映数据元素之间的逻辑关系,而与他们在计算机中的存储位置无关:
- 集合(数学中集合的概念):数据结构中的元素之间除了“同属一个集合” 的相互关系外,别无其他关系;
- 线性结构:数据结构中的元素存在一对一的相互关系;
- 树形结构:数据结构中的元素存在一对多的相互关系;
- 图形结构:数据结构中的元素存在多对多的相互关系。
- 数据的物理结构/存储结构:是描述数据具体在内存中的存储(如:顺序结构、链式结构、索引结构、哈希结构)等,一种数据逻辑结构可表示成一种或多种物理存储结构。
List 接口(数组+链表)
- List接口特点:
- List集合所有的元素是以一种线性方式进行存储的,例如,存元素的顺序是11、22、33。那么集合中,元素的存储就是按照11、22、33的顺序完成的)
- 它是一个元素存取有序的集合。即元素的存入顺序和取出顺序有保证。
- 它是一个带有索引的集合,通过索引就可以精确的操作集合中的元素(与数组的索引是一个道理)。
- 集合中可以有重复的元素,通过元素的equals方法,来比较是否为重复的元素。
List接口中常用的方法
List作为Collection集合的子接口,不但继承了Collection接口中的全部方法,而且还增加了一些根据元素索引来操作集合的特有方法
- 添加元素
a.add(添加元素);
- 删除元素
a.rempve(数组下标);
- 将元素添加到指定的位置
a.add(下标,添加元素);
- 修改指定下标元素
a.set(下标,添加元素);
- 获取元素下标的值
a.set(a.size()-1,元素名);
- 获取元素第一次出现的下标
int indexOf = a.indexOf(元素名)
- 获取元素第一次出现的下标
int lastIndexOf = a.lastIndexOf()(元素名)
List集合的遍历方式
- “ListIterator” List 集合额外提供了一个 listIterator() 方法,该方法返回一个 ListIterator 列表迭代器对象, ListIterator 接口继承了 Iterator 接口,提供了专门操作 List 的方法
* void add():通过迭代器添加元素到对应集合
* void set(Object obj):通过迭代器替换正迭代的元素
* void remove():通过迭代器删除刚迭代的元素
* boolean hasPrevious():如果以逆向遍历列表,往前是否还有元素。
* Object previous():返回列表中的前一个元素。
* int previousIndex():返回列表中的前一个元素的索引
* boolean hasNext()
* Object next()
* int nextIndex()
- 遍历
- ListIterator
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("张三");
list.add("李四");
list.add("王五");
list.add("马六");
list.add("陈七");
System.out.println("从后往前遍历:");
ListIterator<String> listIterator = list.listIterator(list.size());
while(listIterator.hasPrevious()){
int previousIndex = listIterator.previousIndex();
String previous = listIterator.previous();
System.out.println(previousIndex + ":" + previous);
}
}
- 增强for遍历
List<String> list;
@Before
public void test01(){
list = new ArrayList<>();
list.add("张三");
list.add("李四");
list.add("王五");
list.add("马六");
list.add("陈七");
}
@Test
public void test02(){
for (String s : list) {
System.out.println("增强for = " + s);
}
}
- 迭代器遍历
List<String> list;
@Before
public void test01(){
list = new ArrayList<>();
list.add("张三");
list.add("李四");
list.add("王五");
list.add("马六");
list.add("陈七");
}
@Test
public void test02(){
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()){
String ele = iterator.next();
System.out.println("迭代器遍历 = " + ele);
}
}
- 普通for遍历
List<String> list;
@Before
public void test01(){
list = new ArrayList<>();
list.add("张三");
list.add("李四");
list.add("王五");
list.add("马六");
list.add("陈七");
}
@Test
public void test02(){
for (int index = 0; index < list.size(); index++) {
String ele = list.get(index);
System.out.println("ele = " + ele);
}
}
List 的实现类
- ArrayList VS Vector
-
ArrayList是新版的动态数组,线程不安全,效率高,
Vector是旧版的动态数组,线程安全,效率低。 -
动态数组的扩容机制不同
ArrayList扩容为原来的1.5倍,
Vector 如果capacityIncrement为0 扩容增加为原来的2倍,
否则容量为 旧的长度+capacityIncrement。 -
数组的初始化容量
数组的初始化容量,如果在构建ArrayList与Vector的集合对象时,
没有显式指定初始化容量,那么Vector的内部数组的初始容量默认为10,
而ArrayList在JDK1.6及之前的版本也是10,
JDK1.7之后的版本ArrayList初始化为长度为0的空数组,
之后在添加第一个元素时,再创建长度为10的数组。
- LinkedList
-
LinkedList是List接口的另一个常用实现类。
-
LinkedList底层存储数据使用链表结构(双向链表),
特点:增删快,查询慢。
(双向链表):底层是双向链表新增了操作头尾的方法
- LinkedLis的底层结构:
队列和栈
栈
- 堆栈是一种先进后的结构 (FILO : first in last out)
堆栈方法 | 等效 Deque 方法 |
---|---|
push(E) | addFirst(E) |
pop() | removeFirst() |
peek() | peekFirst() |
- 体现栈结构的操作方法:
- peek()方法:查看栈顶元素,不弹出
- pop()方法:弹出栈
- push(E e)方法:压入栈
队列
- 队列(Queue)是一种(但并非一定)先进先出的结构。(FIFO : first in first out)
抛出异常 | 返回特殊值 | |
---|---|---|
插入 | add(e) | offer(e) |
移除 | remove() | poll() |
检查 | element() | peek() |