JavaSE集合之List
Posted LanceToBigData
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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)共同点:都是线程不安全的
以上是关于JavaSE集合之List的主要内容,如果未能解决你的问题,请参考以下文章