java数据结构原理_java几种数据结构原理

1、ArrayList

//初始化一个空数组

public ArrayList() {

this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;

}

private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

//添加元素

public boolean add(E e) {

//设置容量

ensureCapacityInternal(size + 1); // Increments modCount!!

//当前数组大小+1,并设置值

elementData[size++] = e;

return true;

}

private void ensureCapacityInternal(int minCapacity) {

//判断数组为空设置初始化大小为 DEFAULT_CAPACITY = 10;

if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {

minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);

}

//

ensureExplicitCapacity(minCapacity);

}

private void ensureExplicitCapacity(int minCapacity) {

modCount++;

// overflow-conscious code

if (minCapacity - elementData.length > 0)

//真正的设置容量的方法

grow(minCapacity);

}

private void grow(int minCapacity) {

//判断当前数组容量,如果不够则按一定的规则设置新的长度

int oldCapacity = elementData.length;

int newCapacity = oldCapacity + (oldCapacity >> 1);

if (newCapacity - minCapacity < 0)

newCapacity = minCapacity;

if (newCapacity - MAX_ARRAY_SIZE > 0)

newCapacity = hugeCapacity(minCapacity);

//拷贝老的数组到新数组

elementData = Arrays.copyOf(elementData, newCapacity);

}

可见底层实现就是数组,通过改变数组长度来实现可变数组

2、LinkedList

//链表添加元素

public boolean add(E e) {

linkLast(e);

return true;

}

//链尾添加元素

void linkLast(E e) {

//链表最后一个元素

final Node l = last;

//新建一个链表元素,设置上一个元素为l,下一个元素是null

final Node newNode = new Node<>(l, e, null);

//设置链表的最后一个元素为新建的元素

last = newNode;

//如果上一个元素为空则当前元素为第一个元素

if (l == null)

first = newNode;

//否则设置上一个节点的下一个元素是当前元素

else

l.next = newNode;

//链表大小加1

size++;

modCount++;

}

private static class Node {

//链表存储的数据

E item;

//链表下一个元素的引用

Node next;

//链表上一个元素的引用

Node prev;

Node(Node prev, E element, Node next) {

this.item = element;

this.next = next;

this.prev = prev;

}

}

底层实现就是一个双向链表结构

3、HashMap

public V put(K key, V value) {

//hash(key) 计算key的hash值

return putVal(hash(key), key, value, false, true);

}

//根据hashCode方法计算

static final int hash(Object key) {

int h;

return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);

}

final V putVal(int hash, K key, V value, boolean onlyIfAbsent,

boolean evict) {

//定义单向链表结构数组

Node[] tab; Node p; int n, i;

//如果单向链表=null则调用resize方法

if ((tab = table) == null || (n = tab.length) == 0)

//重置链表数组

n = (tab = resize()).length;

//如果在链表结构的数组上不存在当前hash值对应的值,则直接创建新的链表节点存放在(n - 1) & hash的位置

if ((p = tab[i = (n - 1) & hash]) == null)

tab[i] = newNode(hash, key, value, null);

//如果hash值对应的数组位置有值作如下处理

else {

Node e; K k;

//判断hash值相等并且(地址相等或者equals方法相等),hash值相等并且equals比较也想等

if (p.hash == hash &&

((k = p.key) == key || (key != null && key.equals(k))))

e = p;

else if (p instanceof TreeNode)

e = ((TreeNode)p).putTreeVal(this, tab, hash, key, value);

else {

//遍历单向链表

for (int binCount = 0; ; ++binCount) {

//获取链表下一个元素 如果到链表末尾

if ((e = p.next) == null) {

//则创建新的元素追加到链表末尾

p.next = newNode(hash, key, value, null);

//如果binCount操作tree结构的阈值>=8-1则初始化树

if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st

treeifyBin(tab, hash);

break;

}

//链表当前元素hash值和equals值相等,则直接跳出循环

if (e.hash == hash &&

((k = e.key) == key || (key != null && key.equals(k))))

break;

p = e;

}

}

//如果在链表找到hash值和equals值相等则重新设置当前元素值

if (e != null) { // existing mapping for key

V oldValue = e.value;

if (!onlyIfAbsent || oldValue == null)

e.value = value;

afterNodeAccess(e);

return oldValue;

}

}

++modCount;

if (++size > threshold)

resize();

afterNodeInsertion(evict);

return null;

}

底层实现是一个可变数组,每一个数组存储是一个链表结构数据,通过hash值来决定元素存放位置

4、HashSet

public boolean add(E e) {

//map的结构HashMap,PRESENT = new Object()

return map.put(e, PRESENT)==null;

}

可见HashSet的实现就是Value= new Object()的HashMap

5、HashTable

//有synchronized关键字说明是线程安全的

public synchronized V put(K key, V value) {

// Make sure the value is not null

if (value == null) {

throw new NullPointerException();

}

// Makes sure the key is not already in the hashtable.

Entry,?> tab[] = table;

int hash = key.hashCode();

int index = (hash & 0x7FFFFFFF) % tab.length;

@SuppressWarnings("unchecked")

//通过hash值查找元素

Entry entry = (Entry)tab[index];

//如果找到元素并遍历查找当前位置链表结构下是否存在hash值相等并且equals也想等,

//如果找到则设置新值后返回旧值

for(; entry != null ; entry = entry.next) {

if ((entry.hash == hash) && entry.key.equals(key)) {

V old = entry.value;

entry.value = value;

return old;

}

}

//添加新元素

addEntry(hash, key, value, index);

return null;

}

private void addEntry(int hash, K key, V value, int index) {

modCount++;

Entry,?> tab[] = table;

if (count >= threshold) {

//重置数组,并且拷贝旧的数组到新数组

rehash();

tab = table;

hash = key.hashCode();

index = (hash & 0x7FFFFFFF) % tab.length;

}

@SuppressWarnings("unchecked")

Entry e = (Entry) tab[index];

// 创建新键值对之后在链表头添加当前元素(设置当前元素的下个节点为当前位置元素),并设置到当前位置

tab[index] = new Entry<>(hash, key, value, e);

count++;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值