您的位置:首页 > 编程语言 > Java开发

Java的学习记录:charpter7.集合(ArrayList和LinkedList的区别)

2020-06-11 04:43 471 查看

1.集合

1.1集合的概述

1.java集合框架
List , Set, Map都是接口,前两个继承至Collection接口,Map为独立接口。

Set接口的实现类:HashSetLinkedHashSetTreeSet

List接口的实现类:ArrayListVectorLinkedList

Map接口的实现类:HashtableLinkedHashMapHashMapTreeMap

Collection接口下还有个Queue接口,有PriorityQueue
(来自于网络图片)

2.集合和数组的区别
(1)长度:
数组:长度固定
集合:长度可变
(2)内容:
数组:可以是基本类型,也可以是引用类型
集合:只能是引用类型
(3)元素内容
数组:只能存储同一类型的元素
集合:可以储存不同类型的元素

3.collection集合的通用方法:

1.在集合末尾添加元素
boolean add(E e)

2.若本类集合中有与o的值相等的元素,则删除该元素,并返回true
boolean remove(Object o)

3.删除本类集合中的所有元素
void clear()

4.判断集合中是否包含某元素
boolean contains(Object o)

5.判断集合是否为空
boolean isEmpty()

6.返回集合中的元素个数
int size()

7.将一个类集合中的所有元素添加到另一个集合中
boolean addAll(Collection <?extends E> c)

8.返回一个包含本类集合中所有元素的数组,数组类型为Obejct[]
Object[] toArray()

9.迭代器,集合的专用遍历方式
Iterator iterator()

1.2Collection集合的分类

Colletion集合接口下分为List接口和Set接口,两者继承于Collection
接口。

1.2.1List接口

List接口的特点是:元素按照进入的先后顺序保存,是有序的,并且元素可以重复。
List的特有功能:

1.在制定位置添加元素
void add(int index, E element)

2.根据指定索引删除元素,并返回该元素
E remove(int index)

3.把指定索引位置的元素替换为指定的值,返回替换前的值
E set(int index, E element)

4.返回指定元素在集合中第一次出现的索引
int indexOf(Obejct o)

5.获取指定位置的元素
E get(int index)

6.列表迭代器
ListIteraror listIterator()

7.截取集合
List subList(int fromIndex, int toIndex)

1.ArrayList:
ArrayList是List接口的一种实现类,相当于是一种动态数组,ArrayList在内存中分配连续的内存空间,它的底层数据结构是数组,数组的特点是每个元素都有自己对应的下标,因而,使用ArrayList访问元素的时候是非常方便的,但是如果进行插入或删除操作时,会存在大量挪位置和分配多余空间的操作,对计算机的性能消耗较大,因而,插入或删除元素较慢
代码演示:

/**
* @Description  ArrayList 顺序表(动态数组)
* @date 2020/5/27
*/
public class ArrayList<T> implements List<T>{
/**
* 默认初始容量
*/
private static final int DEFAULT_CAPACITY = 10;
/**
* 默认源数据扩容率
*/
private static final float DEFAULT_EXPAND_RATE = 1.5F;
/**
* 核心源数据
*/
private Object[] elementData;
/**
* 常量空数组
*/
private final Object[] EMPTY_DATA = {};
/**
* 数组拷贝的临时记录点
*/
private Object[] copy = EMPTY_DATA;
/**
* 新元素起始位置,当前数组中元素的数量
*/
private int size;

public ArrayList(){
this(DEFAULT_CAPACITY);
}

public ArrayList(int initCapacity){
if(initCapacity==0){
elementData = EMPTY_DATA;
}else if(initCapacity>0){
elementData = new Object[initCapacity];
}else{
System.err.println("初始化容量错误:initCapacity "+initCapacity);
}
}

private void ensureCapacity(int needCapacity){
int expandCapacity = needExpand(needCapacity);
if(expandCapacity<=0){
return;
}
final int newCapacity = (int)Math.ceil((elementData.length+expandCapacity)*DEFAULT_EXPAND_RATE);
copy = elementData;
elementData = new Object[newCapacity];
System.arraycopy(copy,0,elementData,0,size);
copy = EMPTY_DATA;
}

private int needExpand(int needCapacity){
return needCapacity - (elementData.length-size);
}

@Override
public int size() {
return size;
}

@Override
public boolean isEmpty() {
return size==0;
}

@Override
public Object[] toArray() {
return Arrays.copyOf(elementData,size);
}

@Override
public int indexOf(T t) {
for (int i = 0; i < size; i++) {
if(elementData[i].equals(t)){
return i;
}
}
return -1;
}

@Override
public int lastIndexOf(T t) {
for (int i = size-1; i >= 0; i--) {
if(elementData[i].equals(t)){
return i;
}
}
return -1;
}

@Override
public boolean contains(T t) {
return -1 != indexOf(t);
}

@Override
public void add(T t) {
ensureCapacity(1);
elementData[size++] = t;
}

@Override
public void add(T[] arr) {
ensureCapacity(arr.length);
System.arraycopy(arr,0,elementData,size,arr.length);
size += arr.length;
}

@Override
public void add(List<T> list) {
add((T[])list.toArray());
}

@Override
public T remove(int index) {
if(index<0 || index>=size){
throw new ArrayIndexOutOfBoundsException("index out of bounds : "+index);
}
T t = (T)elementData[index];
for (int i = index; i <size-1 ; i++) {
elementData[i] = elementData[i+1];
}
elementData[--size] = null;
return t;
}

@Override
public boolean remove(T t) {
int index = indexOf(t);
if(-1==index){
return false;
}
remove(index);
return true;
}

@Override
public T get(int index) {
if(index<0 || index>=size){
throw new ArrayIndexOutOfBoundsException("index out of bounds : "+index);
}
return (T)elementData[index];
}

@Override
public void sort(boolean ascend, Comparator<T> comparator) {
if(null==elementData || elementData.length<=1) return;
if(null==comparator) throw new NullPointerException("comparator null pointer exception");
Arrays.sort((T[])elementData,0,size-1,comparator,ascend);
}

//匿名内部类 :接口和抽象类不能直接实例化,但是可以通过匿名内部类实例化
@Override
public Iterator<T> iterator() {
return new Iterator<T>() {
private int index = -1;

@Override
public boolean hasNext() {
return ++index<size;
}

@Override
public T next() {
return (T)elementData[index];
}

@Override
public T remove() {
T t = next();
ArrayList.this.remove(index);
index--;
return t;
}
};
}
}

2.LinkedList:
LinkedList:是List接口的一种实现类,本质上是一种链表的形式,根据链表的形式不同又分为单链表双链表,LinkedList分配的空间是不连续的,不具备数组有下标的特征,因而,在访问元素的时候性能较慢,但是因为链表中的每个节点都是独立的关系,因而在执行插入或删除操作的时候较快,无序分配多余的空间,需要多少节点就分配多少空间,性能较高。
LinkedList的特有功能:

添加:
addFirst()
addLast()
删除:
removeFirst()
removeLast()
获取:
getFirst()
getLast()

代码演示:(双向链表

/**
* @Description  //双向链表
* @date 2020/6/2
*/
public class LinkedList<T> implements List<T> {

/**
* 隐藏在内部的节点:内部类
* @param <T>
*/
//匿名内部类,节点类
private class Node<T> {  //节点类型的类
Node<T> prev; //节点的上一个引用
T t;  //节点值的引用
Node<T> next;//节点的下一个引用

//既没有前节点,又没有后节点
public Node(T t) {
this(null,t,null);
}

//有前节点,没有后节点
public Node(Node<T> prev, T t) {
this(prev, t, null);
}

//有后节点,但是没有前节点
public Node(T t, Node<T> next) {
this(null,t,next);
}

//既有前节点,又有后节点
public Node(Node<T> prev, T t, Node<T> next) {
this.prev = prev;
this.t = t;
this.next = next;
}
}

/**
* 根节点
*/
private Node<T> root;
/**
* 当前节点
*/
private Node<T> curr;

/**
* 当前集合中元素的数量
*/
private int size;

public LinkedList() {
}

public LinkedList(T t) {
add(t);
}

@Override
public int size() {
return size;
}

@Override
public boolean isEmpty() {
return size == 0;
}

@Override
public Object[] toArray() {
Object[] objs = new Object[size];
Iterator<T> it = iterator();
int count = 0;
while(it.hasNext()){
objs[count++] = it.next();
}
return objs;
}

@Override
public int indexOf(T t) {
Iterator<T> it = _iterator(true);
int count = -1;
while(it.hasNext()){
count++;
if(it.next().equals(t)){
return  count;
}
}
return -1;
}

@Override
public int lastIndexOf(T t) {
Iterator<T> it = _iterator(false);
int count = size;
while(it.hasNext()){
count--;
if(it.next().equals(t)){
return count;
}
}
return -1;
}

@Override
public boolean contains(T t) {
return -1 != indexOf(t);
}

@Override
//向链表中添加元素
public void add(T t) {
if (size == 0) { //判空,链表中没有添加元素
root = new Node<>(t);
curr = root;  //链表中没有添加元素,后一个即当前添加的元素curr就是根节点root本身
} else {
//双向链表
Node<T> temp = new Node<>(curr, t); //将新增节点temp的前置引用指向curr的内容t
curr.next = temp;    //将curr的后置引用指向新添加的节点temp
curr = temp;  //现在temp就是原来的curr
}
size++;
}

@Override
//向链表中添加数组(即逐个添加元素)
public void add(T[] arr) {
if (null == arr) return; //判空
for (T t : arr) {
add(t);  //调用添加元素的方法
}
}

@Override
//向链表中添加集合(即逐个添加数组)
public void add(List<T> list) {
if (null == list) return;
add((T[]) list.toArray());  //强转,调用添加数组的方法
}

private Iterator<T> getByIndex(int index){
if(index<0 || index>=size){
throw new ArrayIndexOutOfBoundsException("index out of bounds:"+index);
}
Iterator<T> it = _iterator(true);
while(it.hasNext()){
if (index-- == 0){
return it;
}
}
return null;
}

@Override
public T remove(int index) {
return getByIndex(index).remove();
}

@Override
public boolean remove(T t) {
boolean removed = false;
Iterator<T> it = _iterator(true);
while(it.hasNext()){
if (it.next().equals(t)){
it.remove();
if(!removed){
removed = true;
}
}
}
return removed;
}

@Override
public T get(int index) {
return getByIndex(index).next();
}

@Override
public void sort(boolean ascend, Comparator<T> comparator) {

}

private Iterator<T> _iterator(boolean forward){
return new Iterator<T>() {
private Node<T> temp;
private boolean first = true;

@Override
public boolean hasNext() {
temp = first ? (forward ? root : curr):(forward ? temp.next : temp.prev);
if (first){
first = false;
}
return null != temp;
}

@Override
public T next() {
return temp.t;
}

@Override
public T remove(){
T t = temp.t;
Node<T> prev = temp.prev;
Node<T> next = temp.next;

if(null !=prev){
prev.next = next;
temp.prev = null;
}else{ //如果删除的是第一个
root = next;
if(forward) {
first = true;
}
}
if (null != next){
next.prev = prev;
temp.next = null;
}else { //如果删除的是最后一个
curr = prev;
if (!forward) {
first = true;
}
}
if(!first){
temp = forward ? prev : next;
}
size--;
return t;
}
};
}

@Override
public Iterator iterator() {
return _iterator(true);

}
}

3.Vector
Vector:底层数据结构是数组,查询快,增删慢,线程安全,效率低,可以存储重复元素

总结:
1.ArrayList底层数据结构是数组,查询快,增删慢;LinkedList底层结构是链表,查询慢,增删快
2.ArrayList最常用,线程不安全,在查询时效率高;LinkedList线程不安全,但是在增删时,效率高
3.综上所述,在不考虑线程安全的前提下,需要随机快速访问元素时使用ArrayList插入、删除操作较多时使用LinkedList。

1.2.1Set接口

Set接口的特点是:元素是无序的,仅接受一次该元素,元素不可重复,是唯一的,并做内部排序

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐