• java集合之ArrayList


    ArrayList<E>类:位于java.util包下,是List集合中的一种。


    特点:有序,可重复,实现不同步,底层数据结构是数组,查询快增删慢,允许存储null。每个 ArrayList 实例都有一个容量。该容量是指用来存储列表元素的数组的大小。它总是至少等于列表的大小。随着向 ArrayList 中不断添加元素,其容量也自动增长。在添加大量元素前,应用程序可以使用 ensureCapacity 操作来增加 ArrayList 实例的容量。这可以减少递增式再分配的数量(增长量为原来长度的50%)

    常用构造:

      ArrayList()   :   空参构造,默认容量是10

      ArrayList(int capacity)   :   带参构造,指定初始容量。

    方法:

    1)添加功能

    boolean  add(E e)  : 将指定的元素添加到此列表的尾部。

    void   add(int index,E e): 将指定的元素插入此列表中的指定位置。

    boolean addAll(Collection<? extends E>  c):按照指定 collection 的迭代器所返回的元素顺序,将该 collection 中的所有元素添加到此列表的尾部。

    boolean addAll(int index, Collection<? extends E>  c):从指定的位置开始,将指定 collection 中的所有元素插入到此列表中。

    2)判断功能

    boolean  isEmpty(): 如果此列表中没有元素,则返回 true,注意其内部代码是调用size()方法来判断的

    boolean contains(Object o): 如果此列表中包含指定的元素,则返回 true

    3)获取功能

    int size() : 返回此列表中的元素个数。

    E get(int index):返回此列表中指定位置上的元素。

    4)删除功能

    void clear() :移除此列表中的所有元素。注意:此方法比较暴力,一般不使用。

    E remove(int index):移除此列表中指定位置上的元素。返回:从列表中移除的元素

    boolean remove(Object o):移除此列表中首次出现的指定元素(如果存在)。如果此列表包含此元素则返回true

    5)转换数组功能

    Object[]  toArray():按适当顺序(从第一个到最后一个元素)返回包含此列表中所有元素的数组。

    6)修改功能

    E set(int index,E e) :  用指定的元素替代此列表中指定位置上的元素。返回以前位于该指定位置上的元素

    7)迭代器功能

    public Iterator<E> iterator()  返回按适当顺序在列表的元素上进行迭代的迭代器

    public ListIterator<E> listIterator()  返回此列表元素的列表迭代器(按适当顺序)。

    public ListIterator<E> listIterator(int index)  返回列表中元素的列表迭代器(按适当顺序),从列表的指定位置开始。


     集合的遍历方式:

    1)增强for

    存储自定义类,使用增强for进行集合的遍历。

    package com.list;

    public class Student {
      private String name;
      private int age;
      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 boolean equals(Object obj) {
        if (this == obj)
          return true;
        if (obj == null)
          return false;
        if (getClass() != obj.getClass())
          return false;
        Student other = (Student) obj;
        if (age != other.age)
          return false;
        if (name == null) {
          if (other.name != null)
            return false;
        } else if (!name.equals(other.name))
          return false;
        return true;
      }

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

    package com.list;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.ListIterator;

    public class CollectionTest {
      public static void main(String[] args) {
      //1 创建集合对象
      List<Student> stus = new ArrayList<Student>();
      //2 创建学生对象

      Student stu1 = new Student("zong",23);
      Student stu2 = new Student("wen",23);
      Student stu3 = new Student("wen",23);
      Student stu4 = new Student("wu",23);
      Student stu5 = new Student("wen",23);
      Student stu6 = new Student("ya",24);

      //3 添加学生对象
      stus.add(stu1);
      stus.add(stu2);
      stus.add(stu3);
      stus.add(stu4);
      stus.add(stu5);
      stus.add(stu6);
      //遍历方式一: 将学生集合对象转成数组对象
      Object[] studes = stus.toArray();
       for(int i=0;i<studes.length;i++){
          Student stu = (Student)studes[i];
         System.out.println(stu);
        }
         //遍历方式二:利用迭代器遍历集合
      ListIterator<Student> itor = stus.listIterator();
      while(itor.hasNext()){ //刚开始迭代器指向集合的首部,需要执行next才能获取第一个元素,itor.remove();此方法不能用在next方法之前
        Student stu = itor.next();
        System.out.println(stu);
      }
      //逆序遍历,但是前提必须先前序遍历
      while(itor.hasPrevious()){
        Student stu = itor.previous();
        System.out.println(stu);
      }


        //遍历方式三:普通for循环
      for(int i =0;i<stus.size();i++){

           Student s = stus.get(i);
          System.out.println(stu);
          }

          //遍历方式四:增强for

       for(Student s : stus){

        System.out.println(s);

      }
    }
    }


     遍历集合时出现的ConcurrentModificationException

    遍历集合时如果要实现对集合本身的修改(添加新元素、移除指定元素或修改元素),为防止出现并发修改异常:

    如果使用迭代器遍历

      产生异常原因:迭代器依赖于集合而存在,在迭代过程中,集合进行了修改,迭代器并不知道集合进行了修改,故而报错。也就是说在迭代器遍历集合元素过程中,集合是不能修改元素的。

      解决方案:使用迭代器遍历集合,使用迭代器修改集合(使用迭代器本身提供的功能方法如remove 或者 set、add当然这是list特有的迭代器功能)。

      集合修改之添加元素的效果:元素添加在刚才迭代元素的后面。

      例如:集合修改之移除

      在遍历时如果遇到Student的name="wen"且age=23,则移除此元素。

      Iterator<Student>  iter = stus.iterator();

      while(iter.hasNext()){

        Student s = iter.next(); 

        if(s.getName().equals("wen") && s.getAge()==23){

          iter.remove();

        }

      }

      System.out.println(stus);

      输出结果为

      [Student [name=zong, age=23], Student [name=wu, age=23], Student [name=ya, age=24]]

      例:集合修改之添加

      同样的在遍历时如果遇到Student的name="wu"且age=23,则添加一个元素。

      Student stu7 = new Student("boke",25);

      ListIterator<Student>  iter = stus.listIterator();

      while(iter.hasNext()){

        Student s = iter.next(); 

        if(s.getName().equals("wu") && s.getAge()==23){

          iter.add(stu7);

        }

      }

      System.out.println(stus);

      输出结果:

      [Student [name=zong, age=23], Student [name=wen, age=23], Student [name=wen, age=23], Student [name=wu, age=23], Student [name=boke, age=25], Student [name=wen, age=23], Student [name=ya, age=24]]

    如果不是采用迭代器方式遍历(普通for)

          解决方案:使用集合遍历,使用集合修改。

      集合在遍历时添加元素的效果:在集合的末尾添加元素。

      例:集合修改之移除

      for(int i=0;i<stus.size();i++){

        Student s = stus.get(i);

        if(s.getName().equals("wen") && s.getAge()==23){

          stus.remove(i--);   //防止元素漏掉遍历。

        }

      }

      System.out.println(stus);

      输出结果为:

      [Student [name=zong, age=23], Student [name=wu, age=23], Student [name=ya, age=24]]

      例:集合修改之添加

      Student stu7 = new Student("boke",25);

      for(int i=0;i<stus.size();i++){

        Student s = stus.get(i);

        if(s.getName().equals("wu") && s.getAge()==23){

          stus.add(stu7);   //追加在集合尾部

        }

      }

      System.out.println(stus);

      输出结果为:

      [Student [name=zong, age=23], Student [name=wen, age=23], Student [name=wen, age=23], Student [name=wu, age=23], Student [name=wen, age=23], Student [name=ya, age=24], Student [name=boke, age=25]]


     ArrayList实现元素不可重复的存取:

    思路一:创建一个新的集合

         创建两个集合:一个添加好元素list1和一个空列表list2

      循环遍历list1集合,判断list2集合是否包含list1的元素,如果不包含就添加该元素到list2

        最后就可以得到不含重复元素的集合list2

      List<Student> stus2 = new ArrayList<Student>();
      for(Student s : stus){
        if(!stus2.contains(s))
          stus2.add(s);
      }

      System.out.println(stus);

      输出结果:

      [Student [name=zong, age=23], Student [name=wen, age=23], Student [name=wu, age=23], Student [name=ya, age=24]]

    思路二:不创建新的集合

      借鉴选择排序的思想,去除集合中重复的元素。

      for(int i=0;i<stus.size()-1;i++){
        for(int j=i+1;j<stus.size();j++){
          if(stus.get(i).equals(stus.get(j))){
            stus.remove(j--);
          }
        }
      }
      System.out.println(stus);

      输出结果:

      [Student [name=zong, age=23], Student [name=wen, age=23], Student [name=wu, age=23], Student [name=ya, age=24]]


    ArrayList源码解析:

    1 ArrayList集合为什么可以添加重复的元素??

     添加元素的源码:

    public boolean add(E e) {
      ensureCapacityInternal(size + 1); 
      elementData[size++] = e;
      return true;
    }

    查看源码可知,其底层直接添加,没有做任何判断,返回结果始终为true,表示始终添加成功。

    2 ArrayList集合移除一个和指定元素的相等的元素,是移除一个还是把所有相同的全部移除????

    通过查看源码可知:其移除第一次查找相等的元素,依赖equals()方法,对于自定义对象,需要重写该方法

    public boolean remove(Object o) {
      if (o == null) {
        for (int index = 0; index < size; index++)
          if (elementData[index] == null) { //同时也可以看出ArrayList允许存储Null
            fastRemove(index);
            return true;  //移除成功
        }
      } else {
        for (int index = 0; index < size; index++)
          if (o.equals(elementData[index])) {
            fastRemove(index);
            return true; //一旦查找到就return ,表明移除第一次查找到的元素,而不是全部相等的元素
        }
      }
      return false;
    }

    private void fastRemove(int index) {
      modCount++;
      int numMoved = size - index - 1;  //需要移动元素的个数
      if (numMoved > 0)
        System.arraycopy(elementData, index+1, elementData, index,numMoved); //调用的是native类型方法

      elementData[--size] = null; // 等待垃圾回收器回收
    }

     

  • 相关阅读:
    收藏
    计算矩阵连乘
    关于sublime text
    关于拓扑排序(topologicalsort)
    生成最小树prim算法
    矩阵转置的两种算法
    android wifi热点 socket通信
    AsyncTask异步任务类使用学习
    数据库操作学习
    android 监听短信并发送到服务器
  • 原文地址:https://www.cnblogs.com/zwbg/p/5904419.html
Copyright © 2020-2023  润新知