JavaSE(八)集合之List

前面一篇的corejava讲的是集合的概述,这一篇我将详细的和大家讲解一下Collection下面的List、set、queue这三个子接口。希望大家能得到提升。

一、List接口

1.1、List接口概述

  List类型集合特点:集合中的元素有序且可重复,有下标 。

    注:有序指的是元素放到集合中的顺序和循环遍历出来的顺序一致

  List接口常见的实现类有:ArrayList、LinkedList、Vector等

    对于数据的随机访问,ArrayList效率优于LinkedList,因为LinkedList要移动指针

    对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据

    Vector是线程安全的集合,但是速度慢

1.2、迭代器

  在讲集合之前我们先来说一下迭代器,因为之后我们遍历数据的时候要用到迭代器。

  1)迭代器原理

    迭代器是对集合进行遍历,而每一个集合内部的存储结构都是不同的,所以每一个集合存和取都是不一样,那么就需要在每一个类中定义hasNext()和next()方法,这样做是可以的,

  但是会让整个集合体系过于臃肿,迭代器是将这样的方法向上抽取出接口,然后在每个类的内部,定义自己迭代方式,这样做的好处有二,第一规定了整个集合体系的遍历方式都是hasNext()和next()方法,第二,代码有底层内部实现,使用者不用管怎么实现的,会用即可 。

  我们可以去查看一下ArrayList中迭代器的源码进行分析:  

1,在eclipse中ctrl + shift + t找到ArrayList类
2,ctrl+o查找iterator()方法
3,查看返回值类型是new Itr(),说明Itr这个类实现Iterator接口
4,查找Itr这个内部类,发现重写了Iterator中的所有抽象方法

 3)Iterator中的方法

boolean hasNext() 如果仍有元素可以迭代,则返回 true。 
 E next() 返回迭代的下一个元素。 
 void remove() 从迭代器指向的 collection 中移除迭代器返回的最后一个元素

 3)ListIterator接口

    ListIterator是Iterator的子接口。那为什么要有这个特定的子接口呢?    

      在迭代时,不可以通过集合对象的方法操作集合中的元素。因为会发生ConcurrentModificationException异常。

    所以,在迭代器时,只能用迭代器的放过操作元素,可是Iterator方法是有限的,只能对元素进行判断,取出,删除的操作,

    如果想要其他的操作如添加,修改等,就需要使用其子接口,ListIterator。该接口只能通过List集合的listIterator方法获取。

    这是List中针对迭代的类。我们可以查看源码。这里返回的是一个ListIterator对象

    方法有:

* boolean hasNext()是否有下一个
* boolean hasPrevious()是否有前一个
* Object next()返回下一个元素
* Object previous();返回上一个元素

1.3、List中特有的方法

增
    add(index,element);
    addAll(index,Collection);

删
    remove(index);

改
    set(index,element);
查
    get(index):
    subList(from,to);
    listIterator();
    int indexOf(obj):获取指定元素的位置。
    ListIterator listIterator();

  使用size和get(index)遍历student对象:

//通过size()和get()方法结合使用遍历
        List<Student> list = new ArrayList<>();
        list.add(new Student("张三",12));
        list.add(new Student("李四",23));
        list.add(new Student("王五",54));
        list.add(new Student("小二",34));

        for (int i = 0; i <list.size() ; i++) {
            Student s = (Student)list.get(i);
            System.out.println(s.getName()+":"+s.getAge());
        }

 1.4、集合中并发修改异常产生的原因及解决方案

  需求:我有一个集合,请问,我想判断里面有没有"hello"这个元素,如果有,我就添加一个"world"元素,请写代码实现。    

 List<String> list = new ArrayList<>();
        list.add("meinv");
        list.add("gt");
        list.add("ecg");
        list.add("hello");
        list.add("bvc");
        list.add("aew");

        Iterator<String> it = list.iterator();
        while (it.hasNext()){
            String str = (String)it.next();
            if(str.equals("hello")){
                list.add("world");  //这里会抛出ConcurrentModificationException并发修改异常
            }
        }

  解决方案:

    迭代器迭代元素,迭代器修改元素(ListIterator的特有功能add)   

    集合遍历元素,集合修改元素

ListIterator lit = list.listIterator();        //如果想在遍历的过程中添加元素,可以用ListIterator中的add方法
            while(lit.hasNext()) {
                String str = (String)lit.next();
                if(str.equals("hello")) {
                    lit.add("world");    
                    //list.add("world");
                }
            }

1.5、ArrayList

  1)ArrayList去除集合中字符串的重复值(字符串的内容相同)

    我们可以创建一个新的集合去存储没有重复值的集合

public static void main(String[] args) {
                ArrayList list = new ArrayList();
                list.add("a");
                list.add("a");
                list.add("b");
                list.add("b");
                list.add("b");
                list.add("c");
                list.add("c");
                list.add("c");
                list.add("c");
                
                System.out.println(list);
                ArrayList newList = getSingle(list);
                System.out.println(newList);
            }
        
            /*
             * 去除重复
             * 1,返回ArrayList
             * 2,参数列表ArrayList
             */
            public static ArrayList getSingle(ArrayList list) {
                ArrayList newList = new ArrayList();            //创建一个新集合
                Iterator it = list.iterator();                    //获取迭代器
                while(it.hasNext()) {                            //判断老集合中是否有元素
                    String temp = (String)it.next();            //将每一个元素临时记录住
                    if(!newList.contains(temp)) {                //如果新集合中不包含该元素
                        newList.add(temp);                        //将该元素添加到新集合中
                    }
                }
                return newList;                                    //将新集合返回
            }

  2)去除ArrayList中重复自定义对象元素

    分析:我们通过查看上面的例子中,contains()方法底层也是通过equals来做判断的,所以这里我们需要判断自定义对象的话,我们需要在Student类中重写equals方法。

        这里我们使用contains()方法判断是否包含,底层依赖的是equals()方法

              remove()方法判断是否删除,底层依赖的也是equals()方法

 public boolean remove(Object o) {
        if (o == null) {
            for (int index = 0; index < size; index++)
                if (elementData[index] == null) {
                    fastRemove(index);
                    return true;
                }
        } else {
            for (int index = 0; index < size; index++)
                if (o.equals(elementData[index])) {
                    fastRemove(index);
                    return true;
                }
        }
        return false;
    }
package com.zyh.domain;

public class Student {
    private String name;
    private int age;

    public Student() {
    }

    public Student(String name,int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public boolean equals(Object obj) {
        Student s = (Student)obj;
        return this.name.equals(s.name)&&this.age==this.age;
    }
}
package com.zyh.Collection.List;

import com.zyh.domain.Student;

import java.util.ArrayList;
import java.util.ListIterator;

//去除ArrayList中重复的Student对象元素
public class ArrayListDemo_0010 {
    public static void main(String[] args) {
        ArrayList<Student> list = new ArrayList<>();
        list.add(new Student("哥哥",34));
        list.add(new Student("姐姐",23));
        list.add(new Student("弟弟",15));
        list.add(new Student("花花",13));
        list.add(new Student("姐姐",23));
        list.add(new Student("花花",13));
        list.add(new Student("弟弟",15));
        list.add(new Student("花花",13));
        list.add(new Student("哥哥",34));

        ArrayList<Student> newList =getSignle(list);

        ListIterator<Student> slit = newList.listIterator();
        while (slit.hasNext()){
            Student s = slit.next();
            System.out.println(s.getName()+":"+s.getAge());
        }
    }

    public static ArrayList<Student> getSignle(ArrayList<Student> list){
        ListIterator<Student> slit = list.listIterator();
        ArrayList<Student> newList = new ArrayList<>();
        while (slit.hasNext()){
            Student s = slit.next();
            while (!newList.contains(s)){
                newList.add(s);
            }
        }
        return newList;
    }
}

1.6、LinkedList 

  1)LinkedList特有的方法

  * public void addFirst(E e)及addLast(E e)
    * public E getFirst()及getLast()
    * public E removeFirst()及public E removeLast()
    * public E get(int index);

  2)用LinkedList模拟栈数据结构的集合并测试

    栈:先进后出   队列:先进先出

需求:请用LinkedList模拟栈数据结构的集合,并测试

public class Stack<T>
{
    private LinkedList<T> stack;
    
    //无参构造函数
    public Stack()
    {
        stack=new LinkedList<T>();
    }
    //构造一个包含指定collection中所有元素的栈
    public Stack(Collection<? extends T> c)
    {
        stack=new LinkedList<T>(c);
    }
    //入栈
    public void push(T t)
    {
        stack.addFirst(t);
    }
    //出栈
    public T pull()
    {
        return stack.remove();
    }
    //栈是否为空
     boolean isEmpty()
     {
         return stack.isEmpty();
     }
     
     //打印栈元素
     public void display()
     {
         for(Object o:stack)
             System.out.println(o);
     }
}
            public class Stack {
                private LinkedList list = new LinkedList();        //创建LinkedList对象
                
                public void in(Object obj) {
                    list.addLast(obj);                            //封装addLast()方法
                }
                
                public Object out() {
                    return list.removeLast();                    //封装removeLast()方法
                }
                
                public boolean isEmpty() {
                    return list.isEmpty();                        //封装isEmpty()方法
                }
            }

1.6、Vector

  1)特有方法

    * public void addElement(E obj)
    * public E elementAt(int index)
    * public Enumeration elements()

  2)使用枚举遍历

            Vector v = new Vector();                //创建集合对象,List的子类
            v.addElement("a");
            v.addElement("b");
            v.addElement("c");
            v.addElement("d");
            
            //Vector迭代
            Enumeration en = v.elements();            //获取枚举
            while(en.hasMoreElements()) {            //判断集合中是否有元素
                System.out.println(en.nextElement());//获取集合中的元素
            }

 二、List接口三个子类的特点与区别

2.1、List接口三个子类的特点

  1)ArrayList:     底层数据结构是数组,查询快,增删慢。     线程不安全,效率高。   2)底层数据结构是数组,查询快,增删慢。     线程安全,效率低。      Vector相对ArrayList查询慢(线程安全的)     Vector相对LinkedList增删慢(数组结构)   3)LinkedList:     底层数据结构是链表,查询慢,增删快。     线程不安全,效率高。

2.2、List接口三个子类的区别

   1)Vector和ArrayList的区别     Vector是线程安全的,效率低     ArrayList是线程不安全的,效率高   2)共同点:都是数组实现的   3)ArrayList和LinkedList的区别     ArrayList底层是数组结果,查询和修改快     LinkedList底层是链表结构的,增和删比较快,查询和修改比较慢   4)共同点:都是线程不安全的

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏desperate633

Top 6 常见问题关于Java中的Map1 将Map转换成一个List2 遍历map中的键值对3 根据Map的key值排序4 根据Map的value值排序5 初始化一个静态的不可变的Map6 Has

我们都知道Map是一种键-值对的数据结构,每个键都是唯一的!本文讨论了关于Java中Map使用的最常见的8个问题。为了叙述的简单,所有的例子都会使用泛型。并且本...

813
来自专栏郭耀华‘s Blog

Java集合框架(二)—— HashSet、LinkedHashSet、TreeSet和EnumSet

Set接口   前面已经简绍过Set集合,它类似于一个罐子,一旦把对象'丢进'Set集合,集合里多个对象之间没有明显的顺序。Set集合与Collectio...

3259
来自专栏大闲人柴毛毛

剑指offer代码解析——面试题16反转单链表

本题的详细解析均在代码中注释: /** * 题目:将单链表反转,并输出反转后链表的头结点 * @author 大闲人柴毛毛 */ public class...

41911
来自专栏别先生

Map集合遍历的四种方式理解和简单使用

~Map集合是键值对形式存储值的,所以遍历Map集合无非就是获取键和值,根据实际需求,进行获取键和值 1:无非就是通过map.keySet()获取到值,然后根据...

2246
来自专栏小二的折腾日记

day5(面向对象2)

为什么出现集合类? 数组是固定长度的,集合是可变长度的。 为什么出现这么多的容器? 因为每一个容器对数据的存储方式都有不同。这个存储方式称之为:数据结构。

903
来自专栏向治洪

HashMap实现原理分析

HashMap实现原理分析 HashMap主要是用数组来存储数据的,我们都知道它会对key进行哈希运算,哈系运算会有重复的哈希值,对于哈希值的冲突,HashMa...

2965
来自专栏个人分享

栈的压入、弹出序列

输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序...

972
来自专栏java一日一条

Java ArrayList的不同排序方法

由于其功能性和灵活性,ArrayList是 Java 集合框架中使用最为普遍的集合类之一。ArrayList 是一种 List 实现,它的内部用一个动态数组来存...

1622
来自专栏LanceToBigData

JavaSE(八)集合之Set

今天这一篇把之前没有搞懂的TreeSet中的比较搞得非常的清楚,也懂得了它的底层实现。希望博友提意见! 一、Set接口 1.1、Set集合概述   Set集合:...

2415
来自专栏Java帮帮-微信公众号-技术文章全总结

16(01)总结List的子类,ArrayList,Vector,LinkedList

1:List的子类(掌握) (1)List的子类特点 ArrayList: 底层数据结构是数组,查询快,增删慢 线程不安全,效率高 Vector: ...

3615

扫码关注云+社区

领取腾讯云代金券