/* List接口和常用方法 List接口是Collection接口的子接口 1.List集合类中元素有序(即添加顺序和取出顺序一致)且可重复 2.List集合中的每个元素都有其对应的顺序索引(整型int),即支持索引取出元素(索引从0开始) 4.List接口实现类主要有Vector,LinkedList,Arraylist List接口常用方法 List集合里添加了一些根据索引来操作集合元素的方法 1.void add(int index,Object ele) //在index位置插入ele元素 2.boolean addAll(int index,Collection ele) //从index位置开始将ele中所有元素添加进来 3.Object get(int index) //获取指定index位置的元素 4.int indexOf(Object obj) //返回obj在集合中首次出现的位置 5.int lastIndexOf(Object obj) //返回obj在集合中最后一次出现的位置 6.Object remove(int index) //移除指定index位置的元素,并返回 7.Object set(int index,Object ele) //设置指定index位置元素为ele,即替换 8.List subList(int fromIndex,int toIndex) //返回从fromIndex到toIndex位置的子集合 */ import java.util.ArrayList; import java.util.List; public class List_ { @SuppressWarnings({"all"}) public static void main(String[] args) { //List集合类中元素有序(即添加顺序和取出顺序一致)且可重复 List list = new ArrayList(); list.add("smith"); list.add("mary"); list.add("mary"); System.out.println(list);//[smith, mary, mary] //List集合中的每个元素都有其对应的顺序索引,即支持索引取出元素(索引从0开始) System.out.println(list.get(1));//mary //常用方法 //add list.add(1, "huang"); System.out.println(list);//[smith, huang, mary, mary] //addAll List list2 = new ArrayList(); list2.add("jack"); list2.add("tom"); list.addAll(1, list2); System.out.println(list);//[smith, jack, tom, huang, mary, mary] //get System.out.println(list.get(0));//smith //indexOf System.out.println(list.indexOf("tom"));//2 //lastIndexOf System.out.println(list.lastIndexOf("mary"));//5 //remove list.remove(0); System.out.println(list);//[jack, tom, huang, mary, mary] //set list.set(1, "黄"); System.out.println(list);//[jack, 黄, huang, mary, mary] //subList List returnlist = list.subList(0, 2); System.out.println(returnlist);//[jack, 黄] } }
import java.util.Iterator; import java.util.LinkedList; import java.util.List; /* List的三种遍历方式(List接口实现类Vector,LinkedList,Arraylist都适用) 1.使用iterator Iterator iterator = xxx.iterator(); while(iter.hasNext()){ Object x = iterator.next(); } 2.使用增强for循环 for(元素类型 元素名:集合名或数组名){ 访问元素 } 3.使用普通for for(int i=0;i<list.size();i++){ list.get(i); } */ public class List02 { @SuppressWarnings({"all"}) public static void main(String[] args) { List list = new LinkedList(); list.add("jack"); list.add("tom"); list.add("mary"); list.add("smith"); //遍历 System.out.println("===========使用迭代器=============="); Iterator iterator = list.iterator(); while (iterator.hasNext()) { Object obj = iterator.next(); System.out.println(obj); } System.out.println("===========使用增强for=============="); for (Object obj :list) { System.out.println(obj); } System.out.println("===========使用普通for=============="); for (int i = 0; i < list.size(); i++) { System.out.println(list.get(i)); } } }
import java.util.ArrayList; /* 1.ArrayList可以加入null,且可放多个 2.ArrayList是由数组来实现数据存储的 3.ArrayList基本等同于Vector,除了ArrayList是线程不安全(源码没有synchronized) 在多线程情况下,不建议使用ArrayList ArrayList底层结构 1.ArrayList维护了一个Object类的数组elementData transient Object[] elementData //transient表示该属性不会被序列化 2.当创建ArrayList对象时,如果使用的是无参构造器,则初始elementDate容量为0 第1次添加则扩容elementData为10,如再次扩容,则扩容elementData的1.5倍 0-->10-->15-->22-->... 3.如果使用的为指定大小的构造器,初始容量为指定大小,如需扩容,则扩容elementData的1.5倍 */ @SuppressWarnings({"all"}) public class List03 { public static void main(String[] args) { // 使用无参构造器创建 ArrayList 对象 ArrayList list = new ArrayList(); //ArrayList list = new ArrayList(8); // 使用 for 给 list 集合添加 1-10 数据 for (int i = 1; i <= 10; i++) { list.add(i); } //使用 for 给 list 集合添加 11-15 数据 for (int i = 11; i <= 15; i++) { list.add(i); } list.add(100); list.add(200); list.add(null); } } /* 使用无参构造器部分源码 public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; } //创建了一个空的elementData数组 public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; //执行list.add,先确定是否要扩容,然后在执行赋值 private static int calculateCapacity(Object[] elementData, int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { return Math.max(DEFAULT_CAPACITY, minCapacity); } //确定minCapacity,第一次扩容为10 private void ensureExplicitCapacity(int minCapacity) { modCount++;//记录集合被修改的次数 // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity);//如果elementData大小不够 就调用grow //使用扩容机制来确定要扩容到多大 private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1);//第一次newCapacity=10,第二次以后按照1.5倍扩容 if (newCapacity - minCapacity < 0) newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); // minCapacity is usually close to size, so this is a win: elementData = Arrays.copyOf(elementData, newCapacity);//扩容使用Arrays.copyOf() } */ /* 使用有参构造器部分源码 public ArrayList(int initialCapacity) { if (initialCapacity > 0) { this.elementData = new Object[initialCapacity]; //创建了一个指定大小elementData数组 } else if (initialCapacity == 0) { this.elementData = EMPTY_ELEMENTDATA; } else { throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); } } */
import java.util.Vector; /* Vector底层结构 1.Vector底层也是一个对象数组,protected Object[] elementData; 2.Vector是线程同步的,即线程安全,操作方法都带有关键字synchronized 3.在开发中,需要线程同步安全时,考虑使用Vector Vector和ArrayList的比较 底层结构 版本 线程安全 扩容倍数 ArrayList 可变数组 jdk1.2 不安全,效率高 无参默认为10,后按1.5倍 有参1.5倍 Vector 可变数组 jdk1.0 安全,效率不高 无参默认为10,后按2倍 有参2倍 */ public class List04 { public static void main(String[] args) { //Vector vector= new Vector(); Vector vector = new Vector(8); for (int i = 0; i < 10; i++) { vector.add(i); } vector.add(66); System.out.println(vector); } } /* 部分源码 //无参默认为10 public Vector() { this(10); //有参方法 public Vector(int initialCapacity) { this(initialCapacity, 0); } //添加数据到Vector public synchronized boolean add(E e) { modCount++; ensureCapacityHelper(elementCount + 1); elementData[elementCount++] = e; return true; } //判断是否需要扩容 private void ensureCapacityHelper(int minCapacity) { // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); } //扩容算法 private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; int newCapacity = oldCapacity + ((capacityIncrement > 0) ? capacityIncrement : oldCapacity); //扩容2倍 10+10 if (newCapacity - minCapacity < 0) newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); elementData = Arrays.copyOf(elementData, newCapacity); } */
/* LinkedList 1.底层实现了双向链表和双端队列特点 2.可以添加任意元素(元素可以重复),包括null 3.线程不安全,没有实现同步 LinkedList底层 1.底层维护了一个双向链表 2.维护了两个属性first和last,分别指向首结点和尾结点 3.每个结点(Node对象)又维护了prev,next,item三个属性 prev指向前一个,next指向后一个,最终实现双向链表 4.LinkedList的元素的添加和删除,不是通过数组完成的,效率较高 */ // 模拟简单的双向链表 public class List05 { public static void main(String[] args) { Node node1 = new Node("jack"); Node node2 = new Node("tom"); Node node3 = new Node("smith"); //连接三个结点,形成双向链表 //jack-->tom-->smith node1.next = node2; node2.next = node3; //smith-->tom-->jack node3.pre = node2; node2.pre = node1; Node first = node1;//让first指向node1,即头结点 Node last = node3;//让last指向node3,即尾结点 //从头遍历 while(true){ if(first == null){ break; } System.out.println(first); first = first.next; } System.out.println("==============="); //从尾遍历 while(true){ if(last == null){ break; } System.out.println(last); last = last.pre; } //链表添加数据 Node node = new Node("huang");//创建结点 //插入到node3前 node.next = node3; node.pre = node2; node3.pre = node; node2.next = node; //重置first,重新指向node1 first = node1; System.out.println("==============="); //从头遍历 while(true){ if(first == null){ break; } System.out.println(first); first = first.next; } //重置last,重新指向node3 last = node3; System.out.println("==============="); //从尾遍历 while(true){ if(last == null){ break; } System.out.println(last); last = last.pre; } } } // 定义一个Node类,表示双向链表的一个结点 class Node{ public Object item;//存放数据 public Node next;//指向下一结点 public Node pre;//指向前一结点 public Node(Object name){ this.item = name; } public String toString(){ return "name=" + item; } }
import java.util.Iterator; import java.util.LinkedList; /* LinkedList的增删改查和遍历方式 ArrayList和LinkedList的比较 底层结构 增删效率 改查效率 ArrayList 可变数组 数组扩容,较低 较高 LinkedList 双向链表 链表追加,较高 较低 一般在程序中,大多数是查询,因此大部分情况下使用ArrayList */ @SuppressWarnings({"all"}) public class List06 { public static void main(String[] args) { LinkedList linkedList = new LinkedList(); //添加结点 linkedList.add(1); linkedList.add(2); linkedList.add(3); System.out.println("linkedList=" + linkedList); //删除结点 linkedList.remove(); //默认删除的是第一个结点 //linkedList.remove(2); System.out.println("linkedList=" + linkedList); //修改某个结点对象 linkedList.set(1, 999); System.out.println("linkedList=" + linkedList); //得到某个结点对象 Object o = linkedList.get(1); System.out.println(o);//999 //LinkedList 实现 List 接口 System.out.println("====使用迭代器===="); Iterator iterator = linkedList.iterator(); while (iterator.hasNext()) { Object next = iterator.next(); System.out.println("next=" + next); } System.out.println("====使用增强for===="); for (Object o1 : linkedList) { System.out.println("o1=" + o1); } System.out.println("====使用普通for===="); for (int i = 0; i < linkedList.size(); i++) { System.out.println(linkedList.get(i)); } } } /* 部分源码(增) LinkedList linkedList = new LinkedList(); public LinkedList() {} //这时linkedList 的属性 first = null last = null public boolean add(E e) { linkLast(e); return true; } //执行添加 void linkLast(E e) { final Node<E> l = last; final Node<E> newNode = new Node<>(l, e, null); last = newNode; if (l == null) first = newNode; else l.next = newNode; size++; modCount++; } //将新的结点,加入到双向链表的最后 */ /* 部分源码(删) removeFirst public E remove() { return removeFirst(); } //执行removeFirst public E removeFirst() { final Node<E> f = first; if (f == null) throw new NoSuchElementException(); return unlinkFirst(f); } //执行unlinkFirst private E unlinkFirst(Node<E> f) { // assert f == first && f != null; final E element = f.item; final Node<E> next = f.next; f.item = null; f.next = null; // help GC first = next; if (next == null) last = null; else next.prev = null; size--; modCount++; return element; } //执行unlinkFirst, 将 f 指向的双向链表的第一个结点删除 */