集合
基本数据结构
- 什么数据结构?计算机存储,组织数据(插入,更新,删除,查询)的方式。
- 意义:可以带来更高的存储或者运行效率。
- 需求:高效率的检索算法,索引技术。
- 作用(模拟):存储班级里学生的信息
- 保存学生信息
- 修改学生信息
- 删除学生信息
- 查询学生信息
- 开发一个工具类(重复代码-----sun公司已经开发好了)
-
需求:假如你是大学程序竞赛的导师,一共有五个参赛名额,1-2个替补。
- 准备一个数组(5)[0,1,2,3,4,5]
- 安排五个学生上场比赛
- 查询某一个学生的位置是几号
- 替换掉2号位置的学生,换一个学生上场
- 3号位置作弊,被罚下场,不能安排替补接替、
- 打印出最后比赛的选手名称
-
让F G 都参加比赛(出现了索引越界异常)
//定义一个copy数组的方法
public String[] copy(String[] src,int newLength){
String[] ret = new String[newLength];
System.arraycopy(src,0,ret,0,size);
return ret;
}
- 性能分析
- 大O表示法。表示时间复杂度,专门用于计算性能相关参数
- 针对我们的比赛,进行性能分析
- 保存操作:
- 保存到最后一位,需要一次。
- 保存到第一个位置,如果当前存在 x 个元素,需要操作 x 次,平均(x+1)/2
- 查询操作:
- 根据索引查找,只需要一次
- 根据名称查,需要x次,平均(x+1)/2
- 修改操作:
- 操作一次
- 删除操作
- 删除最后一个元素,只需要一次
- 删除第1个元素,需要 x 次,平均(x+1)/2
- 保存操作:
- 数组的结构,查询和修改都特别快,保存和删除都比较慢。
单向循环链表
单向循环链表和单向列表的不同是,最后一个节点的next不是指向null,而是指向head节点,形成一个“环”。
双向链表
从名字就可以看出,双向链表是包含两个指针的,pre指向前一个节点,next指向后一个节点,但是第一个节点head的pre指向null,最后一个节点的tail指向null。
双向循环链表
双向循环链表和双向链表的不同在于,第一个节点的pre指向最后一个节点,最后一个节点的next指向第一个节点,也形成一个“环”。而LinkedList就是基于双向循环链表设计的。
- 双向链表的性能分析
- 添加元素:
- 第一个元素或者最后一个元素,操作一次
- 中间插入(x+1)/2
- 删除元素
- 第一个元素或者最后一个元素,操作一次
- 中间元素(x+1)/2
- 查询元素
- 平均(x+1)/2
- 修改元素
- 平均(x+1)/2
- 添加元素:
- 数组结构和链表结构如何选择
- 数组
- 查询和修改都很快
- 新增和删除较慢
- 链表
- 新增和删除很快
- 查询和修改较慢
- 数组
- 栈(Stack)先进后出
- 基于数组实现
- 规定:最后一个是栈顶,第一个元素是栈底
集合
- 集合(jdk1.2) 集合类,直接可以使用
- 集合框架类统一为我们调用,底层是数据结构
- 常用集合类
- List 列表:按照索引存放,允许元素重复
- Map映射:键值对,key - value ,不允许key重复,重复就会覆盖
- Set集合:不按照特定方式存储,不允许重复
Collection 常用方法
//容量大小
int size();
//判断集合是否为空
boolean isEmpty();
//判断是否包含某个元素
boolean contains(Object o);
//迭代器
Iterator<E> iterator();
//
Object[] toArray();
//添加元素
boolean add(E e);
//删除元素
boolean remove(Object o);
//清空
void clear();
//迭代器的使用
Collection c =new ArrayList();
Iterator iterator = c.iterator();
while (iterator.hasNext()){
Object elt = iterator.next();
}
Vector
- 初始容量为10
public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, {
protected Object[] elementData;
protected int elementCount;
public Vector() {
this(10);
}
public Vector(int initialCapacity, int capacityIncrement) {
super();
this.elementData = new Object[initialCapacity];
this.capacityIncrement = capacityIncrement;
}
public synchronized boolean add(E e) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = e;
return true;
}
}
- 底层是object[]数组,引用数据类型
- 实现了基本的增删改查
- 常用方法
- add(object obj)增加
- remove(int index)删除索引位置元素
- remove(“B”)删除指定元素
- set(int index, object obj)修改索引位置元素
- size()返回当前集合中元素长度
- get(int index)查询具体索引的元素
- isEmpty()判断当前集合是否为空
Stack 栈结构
栈是属于List下面的数据结构
class Stack<E> extends Vector<E> {
public Stack() {
}
//添加元素
public E push(E item) {
addElement(item);
return item;
}
//查看栈顶对象
public synchronized E peek() {
int len = size();
if (len == 0)
throw new EmptyStackException();
return elementAt(len - 1);
}
//删除栈顶对象,并且返回
public synchronized E pop() {
E obj;
int len = size();
obj = peek();
removeElementAt(len - 1);
return obj;
ArrayList
- 用来取代Vector类,(Vector是线程安全的,会消耗性能)
- 初始化时候,默认给空数组
- 调用add方法的时候,采取重新初始化数组(new 新数组的时候,不用就浪费了,用的时候扩容,节约空间)
ArrayList 和 Vector的区别
-
Vector是线程安全的,ArrayList是线程不安全的
-
ArrayList 初始化没给容量,add时候才给
-
多线程环境也不会去使用Vector(淘汰了),
Collection collection = Collections.synchronizedCollection(arrayList);给ArrayList加锁
-
擅长 查询和更新
LinkedList 链表
-
是一个双向链表
public class LinkedList<E> transient int size = 0; transient Node<E> first; transient Node<E> last; 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; } }
-
非线程安全的
-
擅长 保存和删除
Set
HashSet
-
特点
- 不允许重复
- 不会记录元素 的添加顺序(使用hashCode())
-
源码分析
public boolean add(E e) { return map.put(e, PRESENT)==null; } public V put(K key, V value) { return putVal(hash(key), key, value, false, true); }
-
如果我们需要将自定义的对象存到hashset里面去,去自动生成hashCode 和 equals
LinkedHashSet
-
特点
- 不允许重复
- 汇集了元素添加顺序
-
底层源码
- 实现了hashset
rn map.put(e, PRESENT)==null;
}
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
} - 实现了hashset
-
如果我们需要将自定义的对象存到hashset里面去,去自动生成hashCode 和 equals
LinkedHashSet
- 特点
- 不允许重复
- 汇集了元素添加顺序
- 底层源码
- 实现了hashset
- 使用的hashMap,使用了链表结构,保证了元素的添加顺序