上文中我们得知了集合的顶层接口Collection,但根据面向对象的特点,子类虽然继承父类的全部方法,但却有自己独有的功能,作为有下标的集合。我们来看下它的不同。
list的独特特点
l 它是一个元素存取有序的集合。例如,存元素的顺序是11、22、33。那么集合中,元素的存储就是按照11、22、33的顺序完成的)。
l 它是一个带有索引的集合,通过索引就可以精确的操作集合中的元素(与数组的索引是一个道理)。
l 集合中可以有重复的元素,通过元素的equals方法,来比较是否为重复的元素。
下面的集合有ArrayList和linkedlist
①创建对象
list<泛型> 变量名=new 子类集合<泛型>();
List<String> list =new ArrayList<String>();
②常用方法
这里和collection唯一不同的是remove方法(移除第一次出现的指定元素)返回值为被删除的元素返回值为被删除的元素,比起collection多了一个返回值,和ArrayList基本一致
③遍历 因为我们发现它有get获取元素的方法,可以用普通for循环,或者增强for,或者迭代器。基本和ArrayList一样
package com.oracle.demo4; import java.util.ArrayList; import java.util.List; public class Demo { public static void main(String[] args) { List<String> list =new ArrayList<String>(); list.add("a"); //在指定位置插入元素 list.add(0,"b"); list.add("c"); //遍历,因为有下标,可以直接遍历 for(int i=0;i<list.size();i++){ System.out.println(list.get(i)); } //删除指定下标的元素 String str=list.remove(2); //修改指定位置上的值 list.set(0, "你好"); System.out.println("删除的元素为"+str); //增强for遍历 for(String s:list){ System.out.println(s); } } }
在list集合中也可以使用Iterator迭代器,但我们注意如果要利用迭代器进行操作要注意出现并发修改异常。也就是
//迭代集合,当有元素为"abc2"时,集合加入新元素"a" Iterator<String> it = list.iterator(); while(it.hasNext()){ String str = it.next(); //判断取出的元素是否是"abc2",是就添加一个新元素 if("abc2".equals(str)){ list.add("a");// 该操作会导致程序出错 } } //打印容器中的元素 System.out.println(list); } } 运行上述代码发生了错误 java.util.ConcurrentModificationException这是什么原因呢? 在迭代过程中,使用了集合的方法对元素进行操作。导致迭代器并不知道集合中的变化,容易引发数据的不确定性。 并发修改异常解决办法:在迭代时,不要使用集合的方法操作元素。 那么想要在迭代时对元素操作咋办?通过ListIterator迭代器操作元素是可以的,ListIterator的出现,解决了使用Iterator迭代过程中可能会发生的错误情况。
list的存储数据结构
简单分为:堆栈、队列、数组、链表。
简单来说,ArrayList是队列、堆栈,队列、数组的存储结构,增删慢,查找快。
linkedlist是连表结构。增删快,查找慢。
l 堆栈,采用该结构的集合,对元素的存取有如下的特点:
n 先进后出(即,存进去的元素,要在它后面的元素依次取出后,才能取出该元素)。例如,子弹压进弹夹,先压进去的子弹在下面,后压进去的子弹在上面,当开枪时,先弹出上面的子弹,然后才能弹出下面的子弹。
n 栈的入口、出口的都是栈的顶端位置
n 压栈:就是存元素。即,把元素存储到栈的顶端位置,栈中已有元素依次向栈底方向移动一个位置。Main方法就是这样子,最后弹出
n 弹栈:就是取元素。即,把栈的顶端位置元素取出,栈中已有元素依次向栈顶方向移动一个位置。
l 链表,采用该结构的集合,对元素的存取有如下的特点:
n 多个节点之间,通过地址进行连接。例如,多个人手拉手,每个人使用自己的右手拉住下个人的左手,依次类推,这样多个人就连在一起了。
n 查找元素慢:想查找某个元素,需要通过连接的节点,依次向后查找指定元素
n 增删元素快:
u 增加元素:操作如左图,只需要修改连接下个元素的地址即可。
u 删除元素:操作如右图,只需要修改连接下个元素的地址即可。
我们得知linkedlist是一个链表结构它的数据域对应的指针域是对应的下一个,如11对应0x02的地址。
我们也从集合三步走。
①创建对象
父类类型<泛型> 变量名=new 子类类型 <泛型>();
list<string> list=new linkedlist<泛型>();
②常用方法
因为是一个链表结构,所以他增删改查都需要加上具体的位置,还有比较重要的一点是判断集合中有没有这个元素 boolean flag=list.isEmpty,返回true或者false,默认是有的false
代码如下:
public static void main(String[] args) { LinkedList<String> arr=new LinkedList<String>(); arr.addFirst("a"); arr.addFirst("b"); arr.addLast("c"); arr.addFirst("d"); //超级for遍历 for(String s:arr){ System.out.println(s); } //移出第一个位置的元素 System.out.println("------------"); arr.removeFirst(); //返回第一个 System.out.println(arr.getFirst()); System.out.println("------------"); arr.removeLast(); System.out.println(arr.getLast()); System.out.println("------------"); System.out.println(); for(String s:arr){ System.out.println(s); } System.out.println("------------"); //清空集合 arr.clear(); //判断集合中是否有元素,布尔值可以直接打印,有元素返回false System.out.println(arr.isEmpty()); System.out.println("------------"); }