杭州专业网站建设公司深圳前十名代运营公司
2026/4/9 20:11:08 网站建设 项目流程
杭州专业网站建设公司,深圳前十名代运营公司,无锡网站建设推广服务,做的单页html怎么放网站List接口 List 列表是Collection集合的子接口#xff0c;List是有序、可索引、可重复元素的集合。 有序#xff1a;是指List中的元素按顺序依次添加可索引#xff1a;是指List中的元素可以像数组一样#xff0c;通过索引获取元素可重复#xff1a;是指List中的元素可重复添…List接口List 列表是Collection集合的子接口List是有序、可索引、可重复元素的集合。有序是指List中的元素按顺序依次添加可索引是指List中的元素可以像数组一样通过索引获取元素可重复是指List中的元素可重复添加List有三种实现类ArrayList: 数组实现随机访问快增删慢需要移动元素LinkedList链表实现增删快随机访问慢Vector 线程安全但性能较低已较少使用List是Collection集合的子接口则自然继承了Collection集合的方法。由于List具有有序、可索引、可重复元素的独特特点因此额外有一些跟索引有关的方法常见方法如下Eget(intindex)// 获取指定索引的元素Eremove(intindex)// 删除指定索引的元素返回被删除的元素对象Eset(intindex,Eelement)// 修改指定索引的元素返回被修改的元素对象原元素voidadd(intindex,Eelement)// 在指定索引添加元素原索引及之后的元素索引往后移publicclassDemo0{publicstaticvoidmain(String[]args){// 创建列表对象ListlistnewArrayList();// 添加元素list.add(hello);list.add(world);list.add(java);// 获取指定索引的元素System.out.println(list.get(1));// world// 在list指定位置添加元素list.add(1,zhang);System.out.println(list);// [hello, zhang, world, java]// 删除指定索引的元素System.out.println(list.remove(1));// zhangSystem.out.println(list);// [hello, world, java]// 修改指定索引的元素System.out.println(list.set(0,hi));// 返回原被修改的元素 hello System.out.println(list); // [hi, world, java]}}需要注意List有两个remove方法但是返回类型和形参不同并不是方法重写。publicclassDemo4{publicstaticvoidmain(String[]args){ListStringlistnewArrayList();list.add(hello);list.add(world);list.add(java);// List接口中的remove方法: E remove(int index)Stringslist.remove(1);// 删除指定索引的元素返回被删除的元素System.out.println(s);// worldSystem.out.println(list);// [hello, java]// Collection接口中的remove方法: boolean remove(Object o)booleanblist.remove(java);// 删除指定元素返回布尔值System.out.println(b);// trueSystem.out.println(list);// [hello]}}List 除了支持Collection集合的迭代器遍历、增强型for循环遍历方法外还支持普通for循环遍历以及ListIterator列表迭代器遍历。比如publicclassDemo5{publicstaticvoidmain(String[]args){// 创建List列表对象ListStringlistnewArrayList();// 添加元素list.add(hello);list.add(world);list.add(java);// 迭代方式1用迭代器IteratorIteratorStringiteratorlist.iterator();// 创建迭代器对象while(iterator.hasNext()){Stringelementiterator.next();System.out.println(当前元素: element);}System.out.println(-----------------);// 迭代方式2用增强for循环for(Stringelement:list){System.out.println(当前元素: element);}// 迭代方式3用普通for循环for(inti0;ilist.size();i){Stringelementlist.get(i);System.out.println(当前元素: element 当前索引为i);}System.out.println(-----------------);// 迭代方式4用列表迭代器ListIteratorListIteratorStringlistIteratorlist.listIterator();while(listIterator.hasNext()){StringelementlistIterator.next();System.out.println(当前元素: element);}}}我们知道Iterator迭代器是一个接口核心方法有hasNext()、next()另外有个remove()方法可以实现集合在迭代遍历过程中安全的删除集合元素解决了Collection对象使用自己的remove()方法造成的异常问题。但是Iterator接口并没有提供添加元素的方法让集合在迭代遍历中途安全的添加元素。而ListIterator这个接口继承Iterator除了继承hasNext()、next()、remove()方法外还额外提供一个set(E e)、add(E e)方法让List在迭代遍历中途也能够安全的设置、添加元素。add(Ee):// 将元素插入到迭代器当前位置即下一次next()调用将返回的元素之前set(Ee):// 替换最后一次访问的元素publicclassDemo6{publicstaticvoidmain(String[]args){// 创建列表对象ListStringlistnewArrayList();// 添加元素list.add(hello);list.add(world);list.add(java);// 用Iterator迭代器遍历列表并删除元素IteratorStringitlist.iterator();while(it.hasNext()){Stringsit.next();System.out.println(s);// 打印遍历的元素if(hello.equals(s)){// 以下删除元素会抛出ConcurrentModificationException异常// list.remove(s);it.remove();// 使用Iterator的remove方法安全删除元素// 以下添加元素会抛出ConcurrentModificationException异常// list.add(python);}}System.out.println(list);// 打印列表 [world, java]System.out.println(----------------);// 创建另外一个列表对象ListStringlist2newArrayList();// 添加元素list2.add(hello);list2.add(world);list2.add(java);// 用ListIterator迭代器遍历列表并删除元素、添加元素ListIteratorStringlitlist2.listIterator();while(lit.hasNext()){Stringslit.next();System.out.println(s);// 打印遍历的元素if(hello.equals(s)){// 以下删除元素会抛出ConcurrentModificationException异常// list2.remove(s);lit.remove();// 使用ListIterator的remove方法安全删除元素// 以下添加元素会抛出ConcurrentModificationException异常// list2.add(python);lit.add(python);// 使用ListIterator的add方法安全添加元素}}System.out.println(list2);// 打印列表 [world, java, python] }}List有4种遍历方式在实际编程过程中选择哪一种呢如果在遍历过程中需要用到索引则需要选择普通for循环如果在遍历过程中需要安全的删除元素则可以使用Iterator迭代器或者ListIterator列表迭代器遍历如果在遍历过程中需要安全的添加元素则只能使用ListIterator列表迭代器遍历List相关的数据结构数据结构是程序在内存中组织数据存储的方式常见的数据结构有栈、队列、数组、链表等。栈栈通常只在一端栈顶进行插入和删除操作另一端栈底是封闭的。栈可以想象成一个桶数据是一层一层的放到桶里去。先进入栈的数据是相对在底层后进入栈的数据相对在顶层。而数据要出栈需要先把上层的数据拿出来。因此越前面入栈的数据出来得越晚而越晚进入栈的数据越靠近栈顶越容易出栈。即栈具有先进后出后进先出的特点。栈的数据添加叫做入栈或压栈站的数据移出叫做出栈或弹栈。队列队列可以想象成一个两边都畅通的管道数据从管道一边进入从另一边出去。先进入队列的数据越靠前越先出队列。即队列具有先进先出后进后出的特点。数组数组是在内存中开辟连续存储空间的数据结构。由于是连续的存储空间因此数组可以用索引快速检索到对应内存空间的数据。数据有一个缺点就是申明了数组大小后数组长度就确定了。数组要存储更多数据则需要申明一个新数组然后把原数组内的数据都复制到新的数组。另外如果用数组存储有序的数据虽然用索引检索的速度很快但是插入新数据、删除新数据的速度很慢这是因为在特定索引顺序位置增加新数据后或者在特定索引顺序位置删除数据后索引后的全部数据都要移动位置。也就是说 链表的“索引检索”通常不如数组直接因为需要从头遍历。综上所述数组的特点是索引检索很快增、删很慢。链表链表可以想象为铁链是用铁环节点组成的一条有序的链条。链表在内存中是用一个个分散的节点组成的。每个链表节点中都有这个节点存储的数据和指向下一个节点的引用双向链表还有指向上一个节点的引用。链表要插入数据如果是在链表首、尾插入则非常快因为只需要在第一个节点或者最后一个节点修改一下对插入新节点的引用即可。如果是在某个索引插入也比较快就只需要从前顺序或从后逆序双向链表才可以找到待插入的索引只需要断除原两个节点的引用将新节点的引用相互链接即可完成插入。相比与数组插入数据需要移动其他数据链表的插入速度快不少。删除数据同理。链表是由内存中一个个节点相互链接组成的因此要按索引顺序检索数据相对较慢因为需要从首节点正序或尾节点逆序一个一个节点引用查找的方式去做检索。综上所述链表的特点是增、删很快但是索引检索很慢。ArrayList源码分析ArrayList是List接口的实现类底层实现是采用数组作为数据结构动态进行扩容。因此ArrayList具有查询速度快基于数组索引查询、增加/删除较慢需要动态扩容或者缩容需要大量移动索引后的数组元素。ArrayList类有个int size实例属性表示ArrayList对象中元素的个数以及默认添加元素所在数组位置的索引。还有个Object[] elementData实例属性表示存储元素的Object数组。为了加深对ArrayList的底层实现原理的理解现模拟ArrayList实例添加数据结合源码进行分析。创建新ArrayList对象publicclassDemo12{publicstaticvoidmain(String[]args){ListStringlistnewArrayList();// 创建新ArrayList对象}}在创建新ArrayList对象时会调用ArrayList的无参构造方法privatestaticfinalObject[]DEFAULTCAPACITY_EMPTY_ELEMENTDATA{};publicArrayList(){this.elementDataDEFAULTCAPACITY_EMPTY_ELEMENTDATA;}从上述源码来看调用无参构造方法后实例属性elementData是一个空数组而实例属性size会被默认初始化int类型则是默认值0。ArrayList对象添加1个元素publicclassDemo12{publicstaticvoidmain(String[]args){ListStringlistnewArrayList();// 创建新ArrayList对象list.add(hello);// 添加第一个元素}}在为新ArrayList对象添加第一个元素时会调用add()方法// 将指定元素追加到此列表的末尾publicbooleanadd(Ee){modCount;add(e,elementData,size);returntrue;}modCount是继承自AbstractList抽象类的实例属性用于记录List结构性修改的次数主要用于迭代器并发修改检测。此处暂不展开。add()方法调用时会调用私有的辅助的add()方法privatevoidadd(Ee,Object[]elementData,ints){if(selementData.length)elementDatagrow();elementData[s]e;sizes1;}由于目前是初始化元素为空的ArrayList实例形参e为待添加的元素hello、elementData为空数组、s为0。因此满足条件s elementData.length执行elementData grow()。此时调用grow()方法并将新的数组赋值给elementData。privateObject[]grow(){returngrow(size1);}grow()扩容方法会调用一个私有的辅助grow()方法/** * 增加容量以确保它至少可以容纳由最小容量参数指定的元素数量。 * * param minCapacity 所需的最小容量 * throws OutOfMemoryError 如果 minCapacity 小于零 */privateObject[]grow(intminCapacity){intoldCapacityelementData.length;if(oldCapacity0||elementData!DEFAULTCAPACITY_EMPTY_ELEMENTDATA){intnewCapacityArraysSupport.newLength(oldCapacity,minCapacity-oldCapacity,/* 最小增长 */oldCapacity1/* 首选增长 */);returnelementDataArrays.copyOf(elementData,newCapacity);}else{returnelementDatanewObject[Math.max(DEFAULT_CAPACITY,minCapacity)];}}由于目前是初始化元素为空的ArrayList实例形参minCapacity为1size为0实参为size 1。局部变量oldCapacity为elementData.length即为0。oldCapacity 为0DEFAULTCAPACITY_EMPTY_ELEMENTDATA为空数组elementData为空数组因此条件oldCapacity 0 || elementData ! DEFAULTCAPACITY_EMPTY_ELEMENTDATA为false执行else代码块return elementData new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];ArrayList定义有/** * 默认初始容量。 */privatestaticfinalintDEFAULT_CAPACITY10;minCapacity为1DEFAULT_CAPACITY常量为10所以Math.max(DEFAULT_CAPACITY, minCapacity)应该是Math.max(10, 1) 10因此新创建一个容量为10的数组进行返回。这说明了ArrayList在添加第一个元素时会创建一个长度为10的数组用于存储元素。回到待执行的方法privatevoidadd(Ee,Object[]elementData,ints){if(selementData.length)elementDatagrow();elementData[s]e;sizes1;}此时ArrayList对象中的实例属性elementData指向长度为10的数组。执行elementData[s] e即数组第0索引指向被添加的元素hello完成元素添加操作。执行完毕后size 1ArrayList对象实例属性size为1表明ArrayList对象有1个元素下一个待添加的元素对象存储到数组索引2。LinkedList源码分析LinkedList是List接口的实现类底层实现是采用双向链表作为数据结构。因此LinkedList的增加、删除较快但是查询速度慢。因为LinkedList采用双向链表因此首、尾插入、获取或删除元素都即可LinkedList额外提供了几个独有的特殊方法// 头部voidaddFirst(Ee)// 将元素插入列表开头EremoveFirst()// 移除并返回第一个元素EgetFirst()// 返回第一个元素// 尾部voidaddLast(Ee)// 将元素插入列表末尾EremoveLast()// 移除并返回最后一个元素EgetLast()// 返回最后一个元素LinkedList有三个实例属性int size表示LinkedList对象中元素的个数Node E first指向链表的第一个节点Node E last指向链表的最后一个节点LinkedList使用双向链表作为数据链表中的节点有三个部分存储元素对象指向下一个节点指向上一个节点privatestaticclassNodeE{Eitem;NodeEnext;NodeEprev;Node(NodeEprev,Eelement,NodeEnext){this.itemelement;this.nextnext;this.prevprev;}}为了加深对LinkedList的底层实现原理的理解现模拟LinkedList实例添加数据结合源码进行分析。创建新LinkedList对象publicclassDemo12{publicstaticvoidmain(String[]args){LinkedListStringlistnewLinkedList();// 创建新LinkedList对象}}创建新LinkedList对象会调用LinkedList的无参构造方法publicLinkedList(){}此时LinkedList对象的实例属性会初始化实例属性size为0first为nulllast为null。LinkedList对象添加1个元素publicclassDemo12{publicstaticvoidmain(String[]args){LinkedListStringlistnewLinkedList();// 创建新LinkedList对象list.add(hello);}}对LinkedList对象添加1个元素会调用方法// 添加元素到列表尾部等同于addLast方法publicbooleanadd(Ee){linkLast(e);returntrue;}此时会调用linkLast方法voidlinkLast(Ee){finalNodeEllast;finalNodeEnewNodenewNode(l,e,null);lastnewNode;if(lnull)firstnewNode;elsel.nextnewNode;size;modCount;}首先将实例属性last赋值给局部变量l由于LinkedList对象没有元素此时last和l都是null。然后new一个节点new Node(l, e, null)这个新节点实例属性prev用于指向上个节点为l即新节点指向null实例属性item为待添加的元素“hello”实例属性next用于指向下一个节点为null。last newNode将LinkedList对象实例属性last指向新添加的节点。由于局部变量l此时为null因此执行条件分支if代码体first newNode将first也指向新添加的节点。LinkedList对象实例属性size即元素数量1。此时LinkedList对象的实例属性size为1first和last都指向添加的第一个元素。LinkedList对象添加第二个元素publicclassDemo12{publicstaticvoidmain(String[]args){LinkedListStringlistnewLinkedList();// 创建新LinkedList对象list.add(hello);// 添加第一个元素list.add(world);// 添加第二个元素}}对LinkedList对象添加第二个元素会调用方法// 添加元素到列表尾部等同于addLast方法publicbooleanadd(Ee){linkLast(e);returntrue;}此时会调用linkLast方法voidlinkLast(Ee){finalNodeEllast;finalNodeEnewNodenewNode(l,e,null);lastnewNode;if(lnull)firstnewNode;elsel.nextnewNode;size;modCount;}首先将实例属性last赋值给局部变量l此时last是指向刚添加的第一个元素所在的node1。然后new一个节点new Node(l, e, null)这个新节点实例属性prev用于指向上个节点为l即新节点指向第一个元素所在的node1实例属性item为待添加的元素“world”实例属性next用于指向下一个节点为null。last newNode将LinkedList对象实例属性last指向新添加的节点之前指向node1。由于局部变量l此时指向node1因此执行条件分支else代码体l.next newNode将l.next也就是node1的next执行新节点。LinkedList对象实例属性size即元素数量1。此时LinkedList对象的实例属性size为2first指向第一个元素所在节点node1last指向第二个元素所在节点node2。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询