java-集合老大哥Collection-大儿子List-详解

List

List接口继承Collection接口,被称为有序的Collection(序列)主要有如下三个特点

  1. 有序
  2. 有索引
  3. 可存在重复元素

常见的实现类:ArrayListLinkedList

List接口中的抽象方法,有一部分和父接口Collection是一样的,而List接口自己独有的方法很好区分,就是方法中带有索引(int index),举例如下

package 集合;
import java.util.ArrayList;
import java.util.List;
public class ListDemo {
    /**
     * add(int index,E)
     * 将元素E插入到列表的指定索引上,原来的元素后移
     * 带有索引的操作,要防止越界问题!不可以超过列表的长度
     * 当index为列表的长度时,插入到列表的末尾,index的取值范围在[0,list.size()]
     *
     * E remove(int index)
     * 删除指定索引上的元素,同时返回被删除的元素
     *
     * E set(int index,E)
     * 修改指定索引上的元素,同时返回被修改前的元素
     * 注意和add方法的区别,index的取值范围在[0-list.size()-1]
     * 因为是在指定的索引上进行修改,在index为列表长度时,该索引没有元素,会出现越界
     */
    public static void function(){
        List<String> list = new ArrayList<String>();
        list.add("one");
        list.add("two");
        list.add("three");
        System.out.println("初始list: "+list);

        list.add(0,"one_insert");
        System.out.println("list头添加元素: "+list);

        list.add(list.size(),"last_insert");
        System.out.println("list尾添加元素: "+list);

        //get(int index) 返回指定索引的元素
        System.out.println("get索引1上的元素:"+list.get(1));

        String removed = list.remove(0);
        System.out.println("删除一个元素后的list: "+list);
        System.out.println("被删除的元素: "+removed);

        String set_changed = list.set(list.size()-1,"last_insert_changed");
        System.out.println("修改最后一个元素后的list: "+list);
        System.out.println("被修改的元素: "+set_changed);
    }
    public static void main(String[] args) {
        function();
    }
}
//输出结果
初始list: [one, two, three]
list头添加元素: [one_insert, one, two, three]
list尾添加元素: [one_insert, one, two, three, last_insert]
get索引1上的元素:one
删除一个元素后的list: [one, two, three, last_insert]
被删除的元素: one_insert
修改最后一个元素后的list: [one, two, three, last_insert_changed]
被修改的元素: last_insert

list的遍历有三种方式:Iterator,for循环,增强for

List<String> list = new ArrayList<String>();
list.add("one");
list.add("two");
list.add("three");

Iterator<String> it = list.iterator();
while(it.hasNext()){
	System.out.println(it.next());
}
for(int i=0;i<list.size();i++){
	System.out.println(list.get(i));
}
for(String str:list){
	System.out.println(str);
}

迭代器的并发修改异常 java.util.ConcurrentModificationException :在遍历的过程中使用了集合的方法如add()等修改了集合的长度,如下

List<String> list = new ArrayList<String>();
list.add("one");
list.add("two");
list.add("three");

//对集合使用迭代器进行获取,获取时判断集合中是否存在 “two” 对象
//若存在,则添加一个元素 "ConcurrentModification"
Iterator<String> it = list.iterator();
while(it.hasNext()){
	String str = it.next();
	//判断字符串是否相等,使用equals()方法,不要使用==
	if(str.equals("two")){
		list.add("ConcurrentModification");
	}
	System.out.println(str);
}

面试时让你看代码写运行结果,千万不要很爽快的写出:one two three ConcurrentModification
Tips在对集合进行遍历的过程中,使用集合的方法修改集合的长度,这是不允许的!!!

List集合数据存储的结构

List接口下有很多个集合,它们存储元素所采用的的结构方式是不同的,因此呈现各自的特点,方便我们在不同的环境下去选择不同的集合来使用,常见的数据存储结构有:堆栈,队列,数组,链表
堆栈

  • 先进后出(子弹装弹,先压进去的子弹在下面,后压进去的子弹在上面,开枪时,后压进的子弹先弹出)
  • 栈的入口和出口都是栈的顶端位置
  • 进栈:存元素,即把元素存储到栈顶的位置,栈中已有的元素依次向栈底方向移动一个位置
  • 出栈:取元素,取出栈顶的元素,栈中已有的元素依次向栈顶方向移动一个位置

队列

  • 先进先出(过安检,排成一列,每个人依次检查,只有前面的人全部检查完毕后,才能排到当前的人进行检查)
  • 队列的入口和出口各占一侧

数组

  • 查找元素快,通过索引可以快速访问指定位置的元素
  • 增删元素慢:指定索引位置增加元素(需要创建一个新数组,将指定新元素存储在指定索引位置,再把原数组元素根据索引,复制到新数组对应索引的位置)指定索引位置删除元素(需要创建一个新数组,把原数组元素根据索引,复制到新数组对应索引的位置,其中原数组中指定索引位置元素不复制到新数组中)

链表

  • 多个节点之间通过地址连接(多个人手拉手,每个人使用自己的右手拉住下个人的左手,以此类推,多个人就连在一起了),节点由两个部分组成:数据域(存储的数值),指针域(存储的地址)
  • 查找元素慢,想查找某个元素,需要通过连接的节点,依次向后查找指定元素
  • 增删元素快,增加和删除元素(只要修改连接下个元素的地址即可)

ArrayList 是 List接口的大小可变的数组的实现,注意,实现不是同步的(线程不安全)

ArrayList集合存储数据的结构是数组结构元素增删慢查找快,由于日常开发中使用最多的功能为查询数据和遍历数据,所以ArrayList是最常用的集合,但是在做程序开发时随意地使用ArrayList完成任何需求是不严谨的,不提倡

扫描二维码关注公众号,回复: 9468408 查看本文章

LinkedList是List接口的链表实现,实现同样不是同步的(线程不安全)

LinkedList集合存储数据的结构是链表结构,方便元素的添加与删除,因为实际开发中对一个集合元素的添加和删除经常涉及到首尾操作,所以LinkedList提供了大量首尾操作的方法,举例如下:

void addFirst(E e) //将指定元素插入此链表的开头
void addLast(E e) //将指定元素添加到此链表的末尾
E getFirst() //返回此链表的第一个元素
E getLast() //返回此链表的最后一个元素
E removeFirst() //删除并返回此链表的第一个元素
E removeLast() //删除并返回此链表的最后一个元素
E pop() //从此链表所表示的堆栈处弹出一个元素 相当于removeFirst()
void push(E e) //将元素推入此链表所表示的堆栈 相当于addFirst()
boolean isEmpty() //如果链表不包含元素,则返回 true

方法测试

package 集合;
import java.util.LinkedList;
/**
 * 自身特点:链表底层实现,查询慢,增删快
 *
 * 使用子类的特有功能,不能多态调用,如 使用 removeFirst()方法,不能如下定义
 * List<String> list = new LinkedList<String>(); //编译看左边,List接口并没有removeFirst()方法
 *
 */
public class LinkedListDemo {
    public static void main(String[] args) {
        function();
    }
    public static void function(){
        /**
         * addFirst(E e) 添加到链表的开头
         * addLast(E e) 添加到链表的末尾
         * E getFirst() 获取到链表的第一个元素
         * E getLast() 获取到链表的最后一个元素
         * E removeFirst() 删除并返回第一元素 
         * E removeLast() 删除并返回最后一个元素
         */
        LinkedList<String> linkedList = new LinkedList<String>();
        linkedList.add("one");
        linkedList.add("two");
        linkedList.addFirst("First");
        linkedList.addLast("Last");

        System.out.println("初始链表:"+linkedList);

        //在get时要确保链表中存在元素,若是先执行clear情况链表,则get方法会产生java.util.NoSuchElementException异常
        // !linkedList.isEmpty()等同于如下if条件判断
        if(linkedList.size()!=0){ //避免NoSuchElement异常,可以先判断链表是否为空
            System.out.println("链表的第一个元素:"+linkedList.getFirst());
            System.out.println("链表的最后一个元素:"+linkedList.getLast());
        }

        String removed_First = linkedList.removeFirst();
        String removed_Last = linkedList.removeLast();
        System.out.println("被删除的第一个元素:"+removed_First+", 被删除的最后一个元素:"+removed_Last);
        System.out.println("删除首尾元素后的链表:"+linkedList);
    }
}
初始链表:[First, one, two, Last]
链表的第一个元素:First
链表的最后一个元素:Last
被删除的第一个元素:First, 被删除的最后一个元素:Last
删除首尾元素后的链表:[one, two]
发布了22 篇原创文章 · 获赞 21 · 访问量 7010

猜你喜欢

转载自blog.csdn.net/weixin_43108122/article/details/100973361