一、ArrayList:作为list接口的主要实现类;线程不安全,效率高;底层使用Object[] elementData存储
1、List接口基本介绍
2、list接口中的常用方法
@Test public void test1(){ //1.List集合类中元素有序(即添加顺序和取出顺序一致)、且可重复 List list = new ArrayList(); list.add("jack"); list.add("tom"); list.add("mary"); list.add("tom"); System.out.println("list=" + list); //2.List集合中的每个元素都有其对应的顺序索引,即支持索引 //索引是从0开始的 System.out.println(list.get(3));//tom ArrayList list=new ArrayList(); list.add(45); list.add("aa"); list.add("你好"); list.add("456"); System.out.println(list); //1.void add(int index,Object ele):在index位置插入ele元素 list.add(1,"bb"); System.out.println(list); //2.boolean addAll(int index,Collection eles):从index位置开始将eles中的所有元素添加进来 List list1 = Arrays.asList(1, 2, 3); list.addAll(list1); System.out.println(list); System.out.println(list.size()); //3.Object get(int index):获取指定index位置元素的值 Object dd = list.get(1); System.out.println(dd); //4.int indexOf(Object obj),返回obj在当前集合中首次出现的位置 int obj = list.indexOf("aa"); System.out.println(obj); //5.int LastIndexOf(Object obj),返回obj在当前集合中末次出现的位置 int lastIndexOf = list.lastIndexOf(45); System.out.println(lastIndexOf); //6.Object remove(int index),移除指定index位置的元素,并返回此元素 list.remove(2); System.out.println(list); //7.Object set(int index,Object ele),设置指定index位置的元素为ele list.set(0,78); System.out.println(list); //8.List subList(int fromIndex,int toIndex):返回从fromIndex到toIndex位置的(左闭右开)子集合 System.out.println(list.subList(3,5)); }
输出结果为:
[45, aa, 你好, 456]
[45, bb, aa, 你好, 456]
[45, bb, aa, 你好, 456, 1, 2, 3]
8
bb
2
0
[45, bb, 你好, 456, 1, 2, 3]
[78, bb, 你好, 456, 1, 2, 3]
[456, 1]
List接口的相关练习
代码实现如下
public class ListExercise02 { @SuppressWarnings({"ALL"}) public static void main(String[] args) { // List list = new ArrayList(); // List list = new LinkedList(); List list = new Vector(); Book book = new Book("红楼梦", 10.5, "曹雪芹"); Book book1 = new Book("西游记", 7.4, "吴承恩"); Book book2 = new Book("水浒传", 9.1, "施耐庵"); list.add(book); list.add(book1); list.add(book2); for (Object obj : list) { System.out.println(obj); } sort(list); System.out.println("排序后"); for (Object obj : list) { System.out.println(obj); } } //冒泡排序,价格从小到大 public static void sort(List list) { int listSize = list.size(); for (int i = 0; i < listSize - 1; i++) { for (int j = 0; j < listSize - 1 - i; j++) { Book book1 = (Book) list.get(j); Book book2 = (Book) list.get(j + 1); if (book1.getPrice() > book2.getPrice()) {//交换 list.set(j, book2); list.set(j + 1, book1); } } } } } class Book { private String name; private double price; private String author; public Book(String name, double price, String author) { this.name = name; this.price = price; this.author = author; } @Override public String toString() { return "名称:" + name + "\t价格:" + price + "\t作者:" + author; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } }
输出结果如下:
名称:红楼梦 价格:10.5 作者:曹雪芹 名称:西游记 价格:7.4 作者:吴承恩 名称:水浒传 价格:9.1 作者:施耐庵 排序后 名称:西游记 价格:7.4 作者:吴承恩 名称:水浒传 价格:9.1 作者:施耐庵 名称:红楼梦 价格:10.5 作者:曹雪芹
以上就是常用的list集合中的方法,仅供参考学习!
下面是关于ArrayList的注意事项如下
代码如下
@SuppressWarnings({"all"}) public class ArrayListDetail { public static void main(String[] args) { //可以放所有元素,包括null元素 //ArrayList 是线程不安全的,可以看源码 没有synchronized /* public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; } */ ArrayList arrayList = new ArrayList(); arrayList.add(null); arrayList.add("jack"); arrayList.add(null); System.out.println(arrayList); } }
输出结果如下:
[null, jack, null]
ArrayList的底层源码分析,先看结论
Vector的底层源码分析
分析Vector源码代码如下:
public class Vector_ { public static void main(String[] args) { Vector vector = new Vector(8); for (int i = 0; i < 10; i++) { vector.add(i); } vector.add(100); System.out.println("vector=" + vector); //解读源码: //1.new Vector() 底层 /* public Vector() { this(10); } 补充:如果是Vector vector = new Vector(8); 走的方法: public Vector(int initialCapacity) { this(initialCapacity, 0); } 2.vector.add(i); 2.1 //下面这个方法就添加数据到vector集合 public synchronized boolean add(E e) { modCount++; ensureCapacityHelper(elementCount + 1); elementData[elementCount++] = e; return true; } 2.2 确定是否需要扩容 条件:minCapacity - elementData.length > 0 private void ensureCapacityHelper(int minCapacity) { // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); } 2.3 //如果需要的数组大小不够用,就扩容,扩容的算法 private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; int newCapacity = oldCapacity + ((capacityIncrement > 0) ? capacityIncrement : oldCapacity); //就是扩容两倍 if (newCapacity - minCapacity < 0) newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); elementData = Arrays.copyOf(elementData, newCapacity); } */ } }
Vector和ArrayList的比较如下:
LinkedList的全面说明
LinkedList底层结构如下
演示双向链表,代码如下
public class LinkedList0 { public static void main(String[] args) { //模拟一个简单的双向链表 Node jack = new Node("jack"); Node tom = new Node("tom"); Node ly = new Node("ly"); //连接三个结点,形成双向链表 //jack->tom->ly jack.next = tom; tom.next = ly; //ly->tom->jack ly.pre = tom; tom.pre = jack; Node first = jack;//让first引用指向jack,就是双向链表的头结点 Node last = ly;//让last引用指向ly,就是双向链表的尾结点 //演示从头到尾进行遍历 System.out.println("===演示从头到尾进行遍历==="); while (true) { if (first == null) { break; } //输出first信息 System.out.println(first); first = first.next; } //演示,从尾到头进行遍历 System.out.println("===从尾到头进行遍历==="); while (true) { if (last == null) { break; } System.out.println(last); last = last.pre; } //演示链表添加对象/数据 //要求:在tom与ly之间,插入一个对象,smith //1.先创建一个Node结点,name就是smith Node smith = new Node("smith"); //下面就把smith加入到双向链表了 smith.next = ly; smith.pre = tom; tom.next = smith; ly.pre = smith; first = jack; System.out.println("===演示从头到尾进行遍历==="); while (true) { if (first == null) { break; } System.out.println(first); first = first.next; } System.out.println("===从尾到头进行遍历==="); last = ly; while (true) { if (last == null) { break; } System.out.println(last); last = last.pre; } } } //定义一个Node类,Node对象表示双向链表的一个结点 class Node { public Object item;//真正存放数据 public Node next; //指向下一个结点 public Node pre;//指向前一个结点 public Node(Object name) { this.item = name; } @Override public String toString() { return "Node name=" + item; } }
输出结果如下
===演示从头到尾进行遍历=== Node name=jack Node name=tom Node name=ly ===从尾到头进行遍历=== Node name=ly Node name=tom Node name=jack ===演示从头到尾进行遍历=== Node name=jack Node name=tom Node name=smith Node name=ly ===从尾到头进行遍历=== Node name=ly Node name=smith Node name=tom Node name=jack
LinkedList底层源码分析,代码如下
public class LinkedListCRUD { 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();//这里默认删除是第一个结点 System.out.println("linkedList=" + linkedList); //修改某个结点对象 linkedList.set(1, 99); System.out.println("linkedList=" + linkedList); //得到某个结点对象 Object o = linkedList.get(1); System.out.println(o);//99 //因为LinkedList是实现了List接口,遍历方式 System.out.println("===LinkedList遍历使用迭代器==="); Iterator iterator = linkedList.iterator(); while (iterator.hasNext()) { Object linkedList1 = iterator.next(); System.out.println("linkedList=" + linkedList1); } //使用增强for循环 System.out.println("===使用增强for循环==="); for (Object o1 : linkedList) { System.out.println(o1); } System.out.println("===LinkedList遍历使用普通for循环==="); for (int i = 0; i < linkedList.size(); i++) { System.out.println(linkedList.get(i)); } //源码阅读 //1. LinkedList linkedList = new LinkedList(); /* public LinkedList() {} 2.这时linkedList的属性 first=null last=null 3.执行 public boolean add(E e) { linkLast(e); return true; } 4.将新的结点,加入到双向链表的最后 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++; } */ /* linkedList.remove();//这里默认删除是第一个结点 1.执行的是 public E remove() { return removeFirst(); } 2.执行 public E removeFirst() { final Node<E> f = first; if (f == null) throw new NoSuchElementException(); return unlinkFirst(f); } 3.执行unlinkFirst,将f 指向的双向链表的第一个结点拿掉 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; } */ } }
输出结果如下
linkedList=[1, 2, 3] linkedList=[2, 3] linkedList=[2, 99] 99 ===LinkedList遍历使用迭代器=== linkedList=2 linkedList=99 ===使用增强for循环=== 2 99 ===LinkedList遍历使用普通for循环=== 2 99
ArrayList和LinkedList的比较