前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【17期】什么情况用ArrayList or LinkedList呢?

【17期】什么情况用ArrayList or LinkedList呢?

作者头像
良月柒
发布于 2020-08-19 13:55:36
发布于 2020-08-19 13:55:36
39500
代码可运行
举报
运行总次数:0
代码可运行

下面以增加和删除元素为例比较ArrayList和LinkedList的不同之处

增加元素到列表尾端:

在ArrayList中增加元素到队列尾端的代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public boolean add(E e){
   ensureCapacity(size+1);//确保内部数组有足够的空间
   elementData[size++]=e;//将元素加入到数组的末尾,完成添加
   return true;      
} 

ArrayList中add()方法的性能决定于ensureCapacity()方法。ensureCapacity()的实现如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public vod ensureCapacity(int minCapacity){
  modCount++;
  int oldCapacity=elementData.length;
  if(minCapacity>oldCapacity){    //如果数组容量不足,进行扩容
      Object[] oldData=elementData;
      int newCapacity=(oldCapacity*3)/2+1;  //扩容到原始容量的1.5倍
      if(newCapacitty<minCapacity)   //如果新容量小于最小需要的容量,则使用最小
                                                    //需要的容量大小
         newCapacity=minCapacity ;  //进行扩容的数组复制
         elementData=Arrays.copyof(elementData,newCapacity);
  }
}

可以看到,只要ArrayList的当前容量足够大,add()操作的效率非常高的。只有当ArrayList对容量的需求超出当前数组大小时,才需要进行扩容。扩容的过程中,会进行大量的数组复制操作。而数组复制时,最终将调用System.arraycopy()方法,因此add()操作的效率还是相当高的。

LinkedList 的add()操作实现如下,它也将任意元素增加到队列的尾端:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public boolean add(E e){
   addBefore(e,header);//将元素增加到header的前面
   return true;
}

其中addBefore()的方法实现如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private Entry<E> addBefore(E e,Entry<E> entry){
     Entry<E> newEntry = new Entry<E>(e,entry,entry.previous);
     newEntry.provious.next=newEntry;
     newEntry.next.previous=newEntry;
     size++;
     modCount++;
     return newEntry;
}

可见,LinkeList由于使用了链表的结构,因此不需要维护容量的大小。从这点上说,它比ArrayList有一定的性能优势,然而,每次的元素增加都需要新建一个Entry对象,并进行更多的赋值操作。在频繁的系统调用中,对性能会产生一定的影响。

增加元素到列表任意位置

除了提供元素到List的尾端,List接口还提供了在任意位置插入元素的方法:void add(int index,E element);

由于实现的不同,ArrayList和LinkedList在这个方法上存在一定的性能差异,由于ArrayList是基于数组实现的,而数组是一块连续的内存空间,如果在数组的任意位置插入元素,必然导致在该位置后的所有元素需要重新排列,因此,其效率相对会比较低。

以下代码是ArrayList中的实现:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public void add(int index,E element){
   if(index>size||index<0)
      throw new IndexOutOfBoundsException(
        "Index:"+index+",size: "+size);
         ensureCapacity(size+1);
         System.arraycopy(elementData,index,elementData,index+1,size-index);
         elementData[index] = element;
         size++;
}

可以看到每次插入操作,都会进行一次数组复制。而这个操作在增加元素到List尾端的时候是不存在的,大量的数组重组操作会导致系统性能低下。并且插入元素在List中的位置越是靠前,数组重组的开销也越大。

而LinkedList此时显示了优势:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public void add(int index,E element){
   addBefore(element,(index==size?header:entry(index)));
}

可见,对LinkedList来说,在List的尾端插入数据与在任意位置插入数据是一样的,不会因为插入的位置靠前而导致插入的方法性能降低。

删除任意位置元素

对于元素的删除,List接口提供了在任意位置删除元素的方法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public E remove(int index);

对ArrayList来说,remove()方法和add()方法是雷同的。在任意位置移除元素后,都要进行数组的重组。ArrayList的实现如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public E remove(int index){
   RangeCheck(index);
   modCount++;
   E oldValue=(E) elementData[index];
  int numMoved=size-index-1;
  if(numMoved>0)
     System.arraycopy(elementData,index+1,elementData,index,numMoved);
     elementData[--size]=null;
     return oldValue;
}

可以看到,在ArrayList的每一次有效的元素删除操作后,都要进行数组的重组。并且删除的位置越靠前,数组重组时的开销越大。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public E remove(int index){
  return remove(entry(index));         
}
private Entry<E> entry(int index){
  if(index<0 || index>=size)
      throw new IndexOutBoundsException("Index:"+index+",size:"+size);
      Entry<E> e= header;
      if(index<(size>>1)){//要删除的元素位于前半段
         for(int i=0;i<=index;i++)
             e=e.next;
     }else{
         for(int i=size;i>index;i--)
             e=e.previous;
     }
         return e;
}

在LinkedList的实现中,首先要通过循环找到要删除的元素。如果要删除的位置处于List的前半段,则从前往后找;若其位置处于后半段,则从后往前找。因此无论要删除较为靠前或者靠后的元素都是非常高效的;但要移除List中间的元素却几乎要遍历完半个List,在List拥有大量元素的情况下,效率很低。

容量参数

容量参数是ArrayList和Vector等基于数组的List的特有性能参数。它表示初始化的数组大小。当ArrayList所存储的元素数量超过其已有大小时。它便会进行扩容,数组的扩容会导致整个数组进行一次内存复制。因此合理的数组大小有助于减少数组扩容的次数,从而提高系统性能。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public  ArrayList(){
  this(10);  
}
public ArrayList (int initialCapacity){
   super();
   if(initialCapacity<0)
       throw new IllegalArgumentException("Illegal Capacity:"+initialCapacity)
      this.elementData=new Object[initialCapacity];
}

ArrayList提供了一个可以制定初始数组大小的构造函数:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public ArrayList(int initialCapacity) 

现以构造一个拥有100万元素的List为例,当使用默认初始化大小时,其消耗的相对时间为125ms左右,当直接制定数组大小为100万时,构造相同的ArrayList仅相对耗时16ms。

遍历列表

遍历列表操作是最常用的列表操作之一,在JDK1.5之后,至少有3中常用的列表遍历方式:

  • forEach操作
  • 迭代器
  • for循环。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
String tmp;
long start=System.currentTimeMills();    //ForEach 
for(String s:list){
    tmp=s;
}
System.out.println("foreach spend:"+(System.currentTimeMills()-start));
start = System.currentTimeMills();
for(Iterator<String> it=list.iterator();it.hasNext();){    
   tmp=it.next();
}
System.out.println("Iterator spend;"+(System.currentTimeMills()-start));
start=System.currentTimeMills();
int size=;list.size();
for(int i=0;i<size;i++){                     
    tmp=list.get(i);
}
System.out.println("for spend;"+(System.currentTimeMills()-start));

构造一个拥有100万数据的ArrayList和等价的LinkedList,使用以上代码进行测试,测试结果:

可以看到,最简便的ForEach循环并没有很好的性能表现,综合性能不如普通的迭代器,而是用for循环通过随机访问遍历列表时,ArrayList表项很好,但是LinkedList的表现却无法让人接受,甚至没有办法等待程序的结束。这是因为对LinkedList进行随机访问时,总会进行一次列表的遍历操作。性能非常差,应避免使用。

总结

ArrayList和LinkedList在性能上各有优缺点,都有各自所适用的地方,总的说来可以描述如下:

1.对ArrayList和LinkedList而言,在列表末尾增加一个元素所花的开销都是固定的。 对ArrayList而言,主要是在内部数组中增加一项,指向所添加的元素,偶尔可能会导致对数组重新进行分配; 而对LinkedList而言,这个开销是统一的,分配一个内部Entry对象。 2.在ArrayList的中间插入或删除一个元素意味着这个列表中剩余的元素都会被移动;而在LinkedList的中间插入或删除一个元素的开销是固定的。 3.LinkedList不支持高效的随机元素访问。 4.ArrayList的空间浪费主要体现在在list列表的结尾预留一定的容量空间,而LinkedList的空间花费则体现在它的每一个元素都需要消耗相当的空间

可以这样说:当操作是在一列数据的后面添加数据而不是在前面或中间,并且需要随机地访问其中的元素时,使用ArrayList会有更好的性能;当操作是在一列数据的前面或中间添加或删除数据,并且按照顺序访问其中的元素时,就应该使用LinkedList了。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-08-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员的成长之路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
2 条评论
热度
最新
朋友圈的广告设计得不错,一般不会造成用户反感
朋友圈的广告设计得不错,一般不会造成用户反感
回复回复点赞举报
微信朋友圈可以说是良心产品了
微信朋友圈可以说是良心产品了
回复回复点赞举报
推荐阅读
被玩儿坏的概念:微信朋友圈广告真的用上了大数据?
  被玩儿坏的概念——微信朋友圈广告真的用上了大数据?   微信朋友圈广告的事儿过去几天了,眼看各路大神一波一波的评述事件,在揣摩数篇大作后,有两个问题值得探讨一下。  第一个疑问:拥有了很多的数据
小莹莹
2018/04/20
8050
被玩儿坏的概念:微信朋友圈广告真的用上了大数据?
如何在朋友圈刷出宝马广告-互联网推荐系统
近期发布了两篇推荐系统的文章: 从0开始做互联网推荐-以58转转为例 从0开始做垂直O2O个性化推荐-以58到家美甲为例 简单介绍了协同过滤推荐、分类预测推荐之外,今天重发一篇原来的旧文,简单介绍一下“基于内容的个性化推荐”。 互联网推荐系统-如何在自己朋友圈刷出宝马广告 2015年初,微信朋友圈首批广告上线: 1)宝马中国 2)vivo智能手机 3)可口可乐 这三则广告出现在每个人的朋友圈信息流里,但是每个用户只能看到其中一个。瞬间,全体微信用户被贴上了三个标签:宝马潜在用户, vivo潜在用户,可口可
架构师之路
2018/03/01
1K0
架构之道:3个程序员成就微信朋友圈日均10亿发布量
前言 截止到2015年7月,微信每月活跃用户约5.49亿,朋友圈每天的发表量(包括赞和评论)超过10亿,浏览量超过100亿。得益于4G网络的发展,以上数据仍有很快的增长,而且相对于PC互联网时代,移动互联网时代的峰值要来得更加凶猛。比如,2015年元月的流量到了平时的2倍,而峰值则达到了平时峰值的2倍,相当于平时正常流量的5倍,这对整个系统的考验是很残酷的。本次分享将简单介绍微信后台团队的开发模式、微信朋友圈的架构以及在性能上的一些工作,供各位参考。 基本介绍 服务器的配置基
用户1263954
2018/06/22
1.5K0
feeds流系统设计概述
什么是 Feeds 流? 从用户层面来说, 各种手机 APP 里面, 特别是社交类的, 我们可以看到关注的内容、好友的动态聚合成一个列表(最典型的就是微信朋友圈)都是 feeds 流的一种形式。
leobhao
2024/06/18
8320
feeds流系统设计概述
IM开发技术学习:揭秘微信朋友圈这种信息推流背后的系统设计
本文由徐宁发表于腾讯大讲堂,原题“程序员如何把你关注的内容推送到你眼前?揭秘信息流推荐背后的系统设计”,有改动和修订。
JackJiang
2021/08/17
1.7K1
微信朋友圈如何自动点赞
我一直都不太喜欢给别人点赞,某一年(貌似是17年)微信出了一次朋友圈年报,那一整年我就点出去了几个赞,要知道当时我微信好友应该有300+。我觉得这是我不喜欢参与社交活动在网络世界的一种体现吧。不给别人点赞也没啥坏处,但你不评不赞,难免会让你和好友之间有些疏远,给别人点赞吧我又嫌麻烦,于是一直想着做个自动点赞的东西,今天基本实现了,虽然诸多不完整和诸多限制,但还是决定分享出来,主要是我觉得还挺好玩的。
全栈程序员站长
2022/08/19
6.5K0
微信朋友圈如何自动点赞
在大数据下,微信眼中的你是什么身份?
想知道微信眼中的你是什么身份吗? 2015年1月,第一批朋友圈广告上线,有网友大呼受到微信的“不公正待遇”,第一批广告投放品牌为“宝马中国”、“vivo”智能手机、“可口可乐”,有人认为收到宝马广告的标签是“精英阶层”,收到可口可乐广告的是“屌丝阶层”。其实不然,请看微信如何定位你的身份! 截止至2016年12月,微信拥有全球共计8.89亿月活跃用户,如此庞大的用户群体,精准的定位是有效广告的保障。首先微信是也是腾讯旗下的,微信的数据源会和QQ用户数据源交叉匹配,微信本身的数据源包括关注的微信公众号、阅
小小科
2018/05/03
6680
在大数据下,微信眼中的你是什么身份?
微信朋友圈第 2 条广告开放,小程序朋友圈广告全量上线
作者:郑智文 & 尹非凡 知晓程序获行业人士爆料,微信很快将发布两个重磅新能力: 朋友圈广告第 2 条全量开放。 小程序朋友圈广告全量上线。 如果说小程序朋友圈广告更多的是商家的狂欢,是 58 万个小程序的大礼包;那么朋友圈第 2 条广告则非常直接地影响到了 10 亿微信用户的使用体验。 从 2015 年 1 月 21 日,朋友圈广告初次上线,3 年时间,微信终于在广告营收压力和商家需求的呼声中再退一步,加大开放朋友圈的广告权限。 朋友圈广告第 2 条开放,也就意味着用户从以前每天仅能接收到 1 条广告变
知晓君
2018/07/04
7820
微信朋友圈技术实现设想
前提 微信朋友圈是我们每天都在用的功能, 但是如果让你来实现一个微信朋友圈, 你会如何做呢? 我来简单设想一下。 实现功能 发朋友圈 评论动态 查看朋友圈(只能查看好友的) 查看评论(只能查看共同好友
烟草的香味
2020/03/11
4.1K0
Redis实现朋友圈,微博等Feed流功能,实现Feed流微服务(业务场景、实现思路和环境搭建)
在互联网领域,尤其现在的移动互联网时代,Feed流产品是非常常见的,比如我们每天都会用到的朋友圈,微博,就是一种非常典型的Feed流产品,还有图片分享网站Pinterest,花瓣网等又是另一种形式的Feed流产品。除此之外,很多App的都会有一个模块,要么叫动态,要么叫消息广场,这些也是Feed流产品,可以说,Feed流产品是遍布天下所有的App中。
共饮一杯无
2022/12/16
1.2K0
Redis实现朋友圈,微博等Feed流功能,实现Feed流微服务(业务场景、实现思路和环境搭建)
微信朋友圈又出新功能!网友:又要失去“朋友”了
4月8日晚间,微信官方宣布,即日起,朋友圈广告@好友评论互动能力全量开放,所有用户均可使用。记者了解到,广告主无须操作,所有朋友圈广告默认具备@好友评论互动的能力。用户收到朋友圈广告后,可以跟点赞、评论一样,在广告的评论区@好友与其进行互动。
半夜喝可乐
2019/04/25
6870
微信朋友圈又出新功能!网友:又要失去“朋友”了
江南春豪掷亿元“全城示爱”,朋友圈广告弱爆了
文:罗超;封面图:分众传媒框架屏幕展示“全城示爱”活动。 每一年情人节都是商家竞逐主战场,近年来在技术手段和互联网玩家的助推之下玩法更加丰富多彩。今年情人节则会出现前所未有的玩法:据悉分众传媒CEO江南春将投入1亿元打造“全城示爱”,玩法很简单,用户关注微信公众账号(qcshiai)提交对TA的表白内容,情人节期间就可在全国分众框架显示屏以弹幕方式显示,并可参与抽奖,支持者包括诺心蛋糕、宝驾租车、携程网、来来惠、奥马冰箱、捷豹、歌诗达邮轮,德芙,寿全斋姜糖、乐心微信秤S1等品牌。就活动形式而看,这意味着一个
罗超频道
2018/04/28
7430
微信斑马系统:微信朋友圈广告背后的利器
随着移动互联网迅速发展,大数据技术为企业带来了前所未有的发展机遇,然而中小企业和传统行业由于其数据量缺乏且单一,技术投入不足的劣势,面对大数据技术发展带来的红利只能望洋兴叹。
大数据真好玩
2019/08/08
2.7K0
洞察|用户调查大数据:35.8%想关闭朋友圈
在微信朋友圈几乎涵盖整个交际圈的今天,发消息、回消息、赞评状态成为我们的日常。然而,不断被投票、代购、广告信息刷屏,也让一些人十分反感,甚至考虑关闭朋友圈。 近日,中国青年报社会调查中心对2000名受
灯塔大数据
2018/04/09
1.2K0
洞察|用户调查大数据:35.8%想关闭朋友圈
朋友圈广告为何能被接受?
腾讯科技 相欣 1月26日报道 昨夜,热议已久的朋友圈广告终于正式上线,首批上线的广告主为宝马、可口可乐和vivo智能手机。 和朋友圈广告系统内测时一致,昨晚上线的三支广告均以文字信息和图片的形式呈现,可“查看详情”看到详细广告信息。依靠右侧标注“推广”二字方便区分。也可选择“我不感兴趣”不再接收提醒消息。 要知道,微信才不是“第一个吃螃蟹的人”,信息流广告这种形式第一次被运用是国外社交平台Twitter,随后Facebook、Instagram、Pinterest,乃至短视频社交应用Vine也都出现了
腾讯大讲堂
2018/02/11
9960
朋友圈广告为何能被接受?
微信朋友圈:应对春节千亿访问量背后的故事
腾讯技术工程官方号
2017/11/30
2.6K0
微信朋友圈:应对春节千亿访问量背后的故事
微信朋友圈广告官网上线:我们一起,做些改变。
2015 年 1 月 21 日,微信朋友圈第一个广告上线,以崭新的角度开启广告主与用户接触及互动的新方式。 在两百多天的时间里,我们不断打破常规、推陈出新,致力于打磨每一个“更懂你”的广告,以更开放的心态拥抱变化和创新。回顾已经发布的广告,每一次推送都让受众眼前一亮。至今,我们已经累计服务来自 20 个不同行业的过百位广告主。 广告如何成为生活的一部分?这是我们始终在探索的课题。让用户喜欢广告,通过展现广告魅力,彰显品牌诉求及价值,这一点是微信朋友圈广告一直追求和坚持的立场。 2015 年 8
腾讯大讲堂
2018/02/12
1.1K0
微信朋友圈广告官网上线:我们一起,做些改变。
腾讯广告算法大赛背后,是 AI 技术与实践落地的一次深入交流
微信朋友圈广告、QQ 广告、小程序广告……这些丰富多样的社交广告,已经悄无声息地渗透到你我的生活当中,并进一步达成信息传递、促进消费升级。在今天,一个广告从锁定目标群体到真正触及用户,到一次成功的「刷屏」,再到交易的成交与转化,背后也越来越多地需要数据、人工智能与算法的协同助力。
AI科技评论
2018/08/16
9160
腾讯广告算法大赛背后,是 AI 技术与实践落地的一次深入交流
朋友圈电商流量开闸,「社交广告+小程序」会重构电商新零售吗?
4 月 12 日,微信广告正式发布公告,朋友圈电商推广面向广告主全量开放。朋友圈电商流量阀门打开,借助于「社交广告+小程序」,腾讯能否重构一个电商新零售格局? 小程序:最适合电商生长的沃土 当传统电商平台的流量正面临枯竭,推广越来越烧钱,依赖平台而生存的企业获取流量的成本高企,最后流量和数据还都不完全属于自己,利润空间也越来越小。种种问题让电商人的焦虑显露出来,越来越多企业开始自建电商零售渠道,小程序的诞生让他们看到了一条新的出路。 4 月 12 日,在「直营电商——社交流量驱动商业未来」2018 腾讯社交
知晓君
2018/07/03
7260
计算广告——广告定向实践
计算广告学涉及到很多的不同的学科知识,包括大规模搜索,文本分析,机器学习,信息检索以及经济学等等。在计算广告中,其核心问题是在给定的环境下,找到用户和广告之间的最佳匹配,在斯坦福大学的计算广告学中如下的定义: Computational advertising = A principled way to find the “best match” between a user in a context and a suitable ad. 对于一条指定的广告,为了寻找用户与广告之间的最佳匹配,需要从大
felixzhao
2018/03/14
3.7K0
计算广告——广告定向实践
推荐阅读
相关推荐
被玩儿坏的概念:微信朋友圈广告真的用上了大数据?
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档