集合和数组:
- 集合和数组相似点
- 都可以存储多个对象,对外作为一个整体存在
- 数组的缺点
- 数组缺乏封装,操作繁琐
- 数组无法直接保存映射关系
- 数组采用连续存储空间,删除和添加效率低下
- 长度必须在初始化时指定,且固定不变
集合框架
- Java集合框架提供了一套性能优良、使用方便的接口和类,它们位于java.util包中。存放在集合中的数据,被称为元素(element)
- 集合架构
- Collection 接口存储一组不唯一,无序的对象
- List 接口存储一组不唯一,有序(索引顺序)的对象
- Set 接口存储一组唯一,无序的对象
- Map接口存储一组键值对象,提供key到value的映射
- Key 唯一 无序
- value 不唯一 无序
List的主要实现类
- List
- 特点:有序 不唯一(可重复)
- ArrayList
- 在内存中分配连续的空间,实现了长度可变的数组
- 优点:遍历元素和随机访问元素的效率比较高
- 缺点:添加和删除需大量移动元素效率低,按照内容查询效率低
【示例1】使用ArrayList存储多个学生的分数
public class TestArrayList1 {
public static void main(String[] args) {
//创建一个ArrayList对象
ArrayList list = new ArrayList();
//向集合中添加多个分数
list.add(78); //加到最后
list.add(89);
list.add(56);
//list.add(new Integer(56));
list.add(89);
list.add(2, 100);//加到指定位置 底层发生了元素大量后移
//list.add(10,20);
ArrayList list2 = new ArrayList();
list2.add(60);
list2.add(58);
list2.add(29);
//list.addAll(list2);
list.addAll(0, list2);
//输出集合中分数
System.out.println(list.size());//4
System.out.println(list);//[]
//遍历1:使用for循环
System.out.println("遍历1:使用for循环");
for(int i=0;i<list.size();i++){
//获取第i个元素
int elem = (Integer)list.get(i);//自动拆箱
//输出第i个元素
System.out.println(i+" "+elem);
}
//遍历2:使用增强的for循环
System.out.println("遍历2:使用增强的for循环");
for(Object elem :list){
//System.out.println(elem);
Integer i = (Integer)elem;
System.out.println(i);
}
//遍历3:使用Iterator迭代器
System.out.println("遍历3:使用Iterator迭代器");
Iterator it = list.iterator();
while(it.hasNext()){//还有元素,没有就结束循环
//如果有,就取出来
int elem = (Integer)it.next();
//输出来
System.out.println(elem); }
}
}
【示例2】使用泛型保证集合操作的安全和简便
public class TestArrayList2 {
public static void main(String[] args) {
//创建一个ArrayList对象
ArrayList<Integer> list = new ArrayList<Integer>();
//向集合中添加多个分数
list.add(78); //加到最后
list.add(89);
list.add(56);
//list.add(new Integer(56));
list.add(89);
list.add(2, 100);
//list.add(10,20);
ArrayList<Integer> list2 = new ArrayList<Integer>();
list2.add(60);
list2.add(58);
list2.add(29);
list.addAll(0, list2);
//输出集合中分数
System.out.println(list.size());//4
System.out.println(list);//[]
//遍历1:使用for循环
System.out.println("遍历1:使用for循环");
for(int i=0;i<list.size();i++){
//获取第i个元素
int elem = list.get(i);//自动拆箱
//输出第i个元素
System.out.println(i+" "+elem);
}
//遍历2:使用增强的for循环
System.out.println("遍历2:使用增强的for循环");
for(Integer elem :list){
System.out.println(elem);
//Integer i = (Integer)elem;
//System.out.println(i);
}
//遍历3:使用Iterator迭代器
System.out.println("遍历3:使用Iterator迭代器");
Iterator<Integer> it = list.iterator();
while(it.hasNext()){//还有元素,没有就结束循环
//如果有,就取出来
int elem = it.next();
//输出来
System.out.println(elem);
}
}
}
【示例3】ArrayList类的更多方法
public class TestArrayList3 {
public static void main(String[] args) {
//创建一个ArrayList对象
ArrayList<Integer> list = new ArrayList<Integer>();
//向集合中添加多个分数
list.add(78); //加到最后
list.add(89);
list.add(56);
//删除
//list.remove(0);
list.remove(new Integer(78));
//更新
list.set(1, 65);
//输出集合中分数
//list.clear();
System.out.println(list.contains(65));
System.out.println(list.toString());
//list.ensureCapacity(100);
}
}
- LinkedList
- 采用双向链表存储方式。
- 缺点:遍历和随机访问元素效率低下
优点:插入、删除元素效率比较高(但是前提也是必须先低效率查询才可。如果插入删除发生在头尾可以减少查询次数)
public class TestLinkedList {
public static void main(String[] args) {
//1.创建一个ArrayList集合对象
//ArrayList<Integer> list = new ArrayList<Integer>();
//LinkedList<Integer> list = new LinkedList<Integer>();
//List<Integer> list = new ArrayList<Integer>();
List<Integer> list = new LinkedList<Integer>();
//2.对集合中的元素进行操作
//2.1 添加
list.add(80);//向末尾添加元素
list.add(80);
list.add(78);//自动装箱
list.add(new Integer(78));
//list.add("Java");
// list.addFirst(12);
// list.addLast(12);
list.add(0,12);
list.add(12);
list.add(100);
list.add(56);
list.add(80);
list.add(2,99);//向指定的位置添加元素
//2.2 查询指定的元素
System.out.println(list.size());//元素的个数
System.out.println(list);
list.remove(1);
System.out.println(list);
System.out.println(list.isEmpty());
}
}
问题1:将ArrayList替换成LinkedList之后,不变的是什么?
- 运算结果没有变
- 执行的功能代码没有变
问题2:将ArrayList替换成LinkedList之后,变化的是什么?
- 底层的结构变了
ArrayList:数组 LinkedList:双向链表
- 具体的执行过程变化了 list.add(2,99)
ArrayList:大量的后移元素
LinkedList:不需要大量的移动元素,修改节点的指向即可
问题3:到底是使用ArrayList还是LinkedList
- 根据使用场合而定
- 大量的根据索引查询的操作,大量的遍历操作(按照索引0--n-1逐个查询一般),建议使用ArrayList
- 如果存在较多的添加、删除操作,建议使用LinkedList
问题4:LinkedList增加了哪些方法
- 增加了对添加、删除、获取首尾元素的方法
- addFirst()、addLast()、removeFirst()、removeLast()、getFirst()、getLast()、
方法摘要 | |
boolean | add(E e)向列表的尾部添加指定的元素(可选操作)。 |
void | add(int index, E element) |
boolean | addAll(Collection<? extends E> c) |
boolean | addAll(int index, Collection<? extends E> c) |
void | clear() 从列表中移除所有元素(可选操作)。 |
boolean | contains(Object o) 如果列表包含指定的元素,则返回 true。 |
boolean | containsAll(Collection<?> c) |
E | get(int index) 返回列表中指定位置的元素。 |
boolean | isEmpty() 如果列表不包含元素,则返回 true。 |
Iterator<E> | iterator() 返回按适当顺序在列表的元素上进行迭代的迭代器。 |
E | remove(int index) |
boolean | remove(Object o) |
boolean | removeAll(Collection<?> c) |
boolean | retainAll(Collection<?> c) |
E | set(int index, E element) 用指定元素替换列表中指定位置的元素(可选操作)。 |
int | size() 返回列表中的元素数。 |
Java中栈和队列的实现类:
Deque和Queue的实现类
1.ArrayDeque 顺序栈 数组
2.LinkedList 链栈 链表
理解Java中栈和队列的接口和实现类:
/**
* push:入栈
* pop:出栈
* peek:获取栈顶元素
*/
public class TestLinkedList2 {
public static void main(String[] args) {
//摞盘子
Deque<String> deque1 = new LinkedList<String>();
deque1.push("盘子1");
deque1.push("盘子2");
deque1.push("盘子3");
System.out.println(deque1.size());
System.out.println(deque1.peek());//get 获取栈顶元素,不移除
System.out.println(deque1.peek());//get 获取栈顶元素,不移除
while(!deque1.isEmpty()){
String elem = deque1.pop();
System.out.println(elem);
}
System.out.println(deque1.size());
}
}