一、HashMap存取效率高原因

1、Hash

也叫散列、哈希。

主要用于信息安全领域中的算法,把长度不同的信息转化为杂乱的128位的编码,找到一种数据内容与地址之间的映射关系。

注意:不同的输入可能会散列成相同的输出

我们最熟悉的Object类中就提供了hashcode的方法。

public native int hashCode();

2、数据结构

Java集合的实现底层大都是基本数据结构的又一层封装。

数组:寻址容易,插入和删除困难

链表正好相反。

HashMap正好将二者互补了一下,推出了链表+数组的组合方式,也叫链表散列、“拉链法”。

结构示意图:

放入元素时,根据key值通过hashcode找到对应数组的位置,放入横向数组的某个格子中。因为前面说到hashcode值不能保证唯一,如果之后hashcode值对应的数组位置中已经有值,就放到相连的链表中。

查找元素也是按这个过程来进行。

代码实现:

注意:每个Node中都持有下一个节点的引用。

3、算法优化

由上面的数据结构介绍,可以看出,在查找的时候,尽量避免查找链表能够大大提高存取效率。

目标:元素尽可能均匀分布,这样查找的时候不必查找链表,效率很高。

思路一:

取模运算,实现是可以实现,但取模运算消耗大、效率不高。

思路二:

首先,&运算比取模运算效率高。

hashmap采用的是下面这种与运算。

大同小异,都是为了减少碰撞,避免hash到同一个位置,使元素分布更均匀。在实现的基础上,考虑性能问题。

ArrayList和LinkedList的大致区别如下:

1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。

2.对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。

3.对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。

上代码:

static final int N=50000;

static long timeList(List list){

long start=System.currentTimeMillis();

Object o = new Object();

for(int i=0;i

list.add(0, o);

}

return System.currentTimeMillis()-start;

}

static long readList(List list){

long start=System.currentTimeMillis();

for(int i=0,j=list.size();i

}

return System.currentTimeMillis()-start;

}

static List addList(List list){

Object o = new Object();

for(int i=0;i

list.add(0, o);

}

return list;

}

public static void main(String[] args) {

System.out.println("ArrayList添加"+N+"条耗时:"+timeList(new ArrayList()));

System.out.println("LinkedList添加"+N+"条耗时:"+timeList(new LinkedList()));

List list1=addList(new ArrayList<>());

List list2=addList(new LinkedList<>());

System.out.println("ArrayList查找"+N+"条耗时:"+readList(list1));

System.out.println("LinkedList查找"+N+"条耗时:"+timeList(list2));

}

当我们在集合中装5万条数据,测试运行结果如下:

显然我们可以看出ArrayList更适合读取数据,linkedList更多的时候添加或删除数据。

ArrayList内部是使用可増长数组实现的,所以是用get和set方法是花费常数时间的,但是如果插入元素和删除元素,除非插入和删除的位置都在表末尾,否则代码开销会很大,因为里面需要数组的移动。

LinkedList是使用双链表实现的,所以get会非常消耗资源,除非位置离头部很近。但是插入和删除元素花费常数时间。

链表结构,通常包含表头,节点1,节点2...节点n,其中节点又包含了数据内容和下个节点的地址。和数组结构(应该叫做顺序表吧大概......)不一样,链表并不用占据连续的内存,它们的区别就不多说了,相信大家都知道。

说说怎么实现吧,既然要用引用的方式来代替指针,那么就需要一个特别的类结构:需要同名的成员保存下一个节点的信息。

public class Node {

private String data;

private Node nextNode;

public String getData() {

return data;

}

public void setData(String data) {

this.data = data;

}

public Node getNextNode() {

return nextNode;

}

public void setNextNode(Node nextNode) {

this.nextNode = nextNode;

}

}

该怎么使用呢?让我们来初始化一个链表吧!

private Node InitNode() {

// 当前节点

Node curNode = new Node();

// 构建头结点

Node head = new Node();

head.setData("head");

head.setNextNode(null);

// 当前节点位于头结点

curNode = head;

// 新增第一个节点

Node n1 = new Node();

// 获取到当前节点,使得的下一个节点设置为n1

curNode.setNextNode(n1);

n1.setData("node1");

n1.setNextNode(null);

// 当前节点位于第一个节点

curNode = n1;

// 第二个节点

Node n2 = new Node();

curNode.setNextNode(n2);

n2.setData("node2");

n2.setNextNode(null);

curNode = n2;

// 第三个节点

Node n3 = new Node();

curNode.setNextNode(n3);

n3.setData("node3");

n3.setNextNode(new Node());

curNode = n3;

// 第四个节点

Node n4 = new Node();

curNode.setNextNode(n4);

n4.setData("node4");

n4.setNextNode(new Node());

curNode = n4;

return head;

}

注意curNode的变动,使得当前节点总落在最后一个节点上,下次插入时就不需要知道前面一个节点的名字了,通过curNode就可以直接插入了。

到底成功了没有,我们来遍历一下。

LinkMain m = new LinkMain();

Node testNode = m.InitNode();

Node iter = testNode.getNextNode();

while (null != iter) {

if (null != iter.getData()) {

System.out.println(iter.getData());

}

iter = iter.getNextNode();

}

输出结果如下:

其中testNode是这样的:

----------------------------分割线---------------------------------------

OK,搞定了初始化和遍历,让我们来试试插入一个节点吧,需求是在某个链表中,第N个位置插入一个节点temp:

新增原理:对于temp节点来说

红色代表的是之前连接,黑色的是之后应该做的。

private Node addNode(Node head, int n, Node temp) {

int i = 0;

while (null != head) {

if (i == n) {

temp.setNextNode(head.getNextNode());

head.setNextNode(temp);

return head;

} else {

head = head.getNextNode();

i++;

}

}

return head;

}

新增后再遍历一下

// 新增一个节点

Node temp = new Node();

temp.setData("tempNode");

temp.setNextNode(null);

Node n3 = m.addNode(testNode, 2, temp);

iter = testNode.getNextNode();

while (null != iter) {

if (null != iter.getData()) {

System.out.println(iter.getData());

}

iter = iter.getNextNode();

}

那么效果如何呢?

其中testNode的内容应该是

OK,结果正确。

----------------------------分割线---------------------------------------

链表的删除节点功能

一开始还搞不定删除,后来画图分析了下,终于解决,放上代码。

难点是设置P,Q两点的指向。其中q是p的下个节点。

应该先找到需要删除的位置。

原理很简单,就是要绕过q来连接p和后后(q后面的节点)节点。

删除前:

删除后:

移除集合效率高还是add高_HashMap存取效率高原因、ArrayList和LinkedList区别、JAVA实现链表的基本功能...相关推荐

  1. Java集合:ArrayList和LinkedList区别?

    ArrayList和LinkedList的大致区别如下: 1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构.  2.对于随机访问get和set,ArrayL ...

  2. java集合框架05——ArrayList和LinkedList的区别

    前面已经学习完了List部分的源码,主要是ArrayList和LinkedList两部分内容,这一节主要总结下List部分的内容. List概括 先来回顾一下List在Collection中的的框架图 ...

  3. Java集合系列之四大常用集合(ArrayList、LinkedList、HashSet、HashMap)的用法

    Java集合系列之四大常用集合(ArrayList.LinkedList.HashSet.HashMap)的用法 ArrayList ArrayList就是传说中的动态数组,用MSDN中的说法,就是A ...

  4. 移除集合效率高还是add高_List、set集合接口分析

    一.List接口详解 1.List接口有三个实现类,ArrayList.LinkedList.Vector 2.三个实现类的异同点: (1)ArrayList: 作为list接口的主要实现类:线程不安 ...

  5. 移除集合效率高还是add高_效率比较--集合

    List ArrayList 实现原理内部封装Object[]数组(若创建时未指定长度 数组初始长度默认为10) 实质为 :无序数组 插入快 查找和删除指定元素慢 总结 O(1) O(N) O(1)  ...

  6. 移除集合效率高还是add高_java集合详解

    1.java集合是什么? java集合实际上是一种经常被运用到的java类库,其中提供了已经实现的的数据结构,省去了程序员再次编写数据结构的事情.在Leetcode中经常会被用到,有很重要的作用. 集 ...

  7. java hashmap存取效率_HashMap为什么存取效率那么高?

    1.Hash 也叫散列.哈希. 主要用于信息安全领域中的算法,把长度不同的信息转化为杂乱的128位的编码,找到一种数据内容与地址之间的映射关系. 注意:不同的输入可能会散列成相同的输出 我们最熟悉的O ...

  8. 两个员工,一个做事认真但效率低,一个迟到早退但效率高,只能留一个我该留哪个?

    我的前老板,曾经开除过两个做事认真,但效率低的员工,公司同事都认为前老板太过严厉,可没想到,后来前老板却因为一个迟到早退,但效率高的员工,改变了整个公司的管理条例,前老板还说:"公司的管理就 ...

  9. HT7180是内置开关管2.7V-12V输入,最高12.8V10A120W以上输出的高功率异步升压转换器,效率最高可达94%

    HT7180是2.7V-12V输入,最高12.8V10A120W以上输出的高功率异步升压转换器,效率最高可达94%,集成22m2功率开关管,ESOP8封装 HT7180输入电压范围:2.7V-12V ...

最新文章

  1. 波卡链Substrate (7)Grandpa协议四“责任安全机制”
  2. 图像条纹检测 python_【连载2.1】结构光三维检测引言面向强反射表面的多传感器三维检测技术研究...
  3. 开源SignalR-Client-CPP使用总结
  4. 古代汉语(王力版)笔记 通论8-9
  5. vim中使用color_coded为c/cpp文件配色
  6. python 全部缩进一行_Python(青铜时代)——基本概念
  7. 最全面的 Fiddler 教程讲解
  8. 火星南极有水,会有生命吗?
  9. 《可以量化的管理学》绪论
  10. caffe学习系列:训练自己的图片集(超详细教程)
  11. word计算机桌面加密,Word文档怎么加密 保护Word文档就靠这4招
  12. OpenCV图像处理知识点梳理
  13. 模拟IC学习笔记 Bandgap设计
  14. android按钮美化(入门)
  15. amp; AMP; 会显示位 | Amp;aMp;amP;会原样显示
  16. influxdb 退出命令
  17. Quectel EC600N-CN 中尺寸物联网首选LTE Cat 1模块[移远通信]
  18. 工信部就垃圾短信问题约谈7家虚拟运营商
  19. 任杰中山大学计算机技术,喜讯 | 港中大(深圳)学子在2020年“外研社·国才杯”全国英语大赛(广东复赛)创造佳绩...
  20. 爬取新浪、网易、今日头条、UC四大网站新闻标题及内容

热门文章

  1. Android基础知识梳理
  2. 毕业生信息管理系统(软件工程课设)
  3. 矩阵相似,矩阵合同,矩阵等价概念总结
  4. 万籁声童子功,练精化气详解
  5. Linux split文件切分工具的使用
  6. Boost中string的split用法
  7. python 赋值方法大全
  8. 基于steam的游戏销量预测 — PART 1 — 爬取steam游戏相关数据的爬虫
  9. J2V8:编译J2V8最新版Jar包
  10. 场景剔除--视锥剔除和硬件剔除