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; // 等待垃圾回收器回收
}

 

 

posted @ 2016-09-24 22:58  zwbg  阅读(449)  评论(0编辑  收藏  举报