List
有序的collection。此接口的用户啊可以对列表中每个元素的插入位置进行精确的控制。用户可以根据元素的整数索引访问元素,并搜索列表中的元素。允许重复元素。
接口特点:有序,索引,可以重复元素
实现类,ArrayList,LinkedList
List接口中的抽象方法,有一部分方法和他的父接口Collection是一样
List接口的自己特有的方法,带有索引的功能
public class ListDemo{
psvm{
}
/*
E set(int index, E)
修改指定索引上的元素
返回被修改之前的元素
*/
public static void fun2(){
List<Integer> list = new List<Integer>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
Integer i = list.set(0,5);
sout(i);
sout(list);
}
/*
E remove(int index)
移除指定索引上的元素
返回被删除之前的元素
*/
public static void func1(){
List<Double> list = new ArrayList<Double>();
list.add(1.1);
list.add(1.2);
list.add(1.3);
list.add(1.4);
Double d = list.remove(0);
sout(d);
sout(list);
}
/*
add(int index, E)
将元素插入到列表的指定索引上
带有索引的操作,防止越界问题
java.lang.IndexOutOfBoundsException
ArrayIndexOutOfBoundsException
StringIndexOutOfBoundsException
*/
public static void function(){
List<String> list = new ArraryList<String>();
list.add("a1");
list.add("a2");
list.add("a3");
list.add("a4");
list.add("a5");
list.add(0,"a0");
}
}
迭代器的并发修改异常
java.util.ConcurrentModificationException
就是在遍历的过程中,使用集合方法修改了集合的长度。这是不允许的
public class ListDemo1{
psvm{
List<String> list = new ArrayList<String>();
list.add("abc1");
list.add("abc2");
list.add("abc3");
list.add("abc4");
list.add("abc5");
//对集合使用迭代器进行获取,获取时候判断集合中是否存在“abc3”对象,
//如果有,添加一个元素“ABC3”
Iterator<String> it = list.iterator();
while(it.hasNext()){
String s = it.next();
//对获取出的元素s,进行判断,是否有abc3
if(s.equals("abc3")){
list.add("ABC3"); //该操作会出错
}
sout(s);
}
}
}
bug解决:此时就通过ListIterator迭代器操作元素是可以的。解决了Iterator迭代过程中可能会发生的错误情况。
List集合存储数据的结构
堆栈:采用该结构的结合,对元素的存取有如下的特点:
先进后出。即,存进去的元素,要在它后面的元素依次取出后,才能取出该元素。
栈的入口,出口的都是栈的顶端位置
压栈:就是存元素。即,把元素存储到栈的顶端位置,栈中已有的元素依次向栈底方向移动一个位置。
弹栈:就是取元素。即,把栈底顶端位置元素取出,栈中已有元素依次向栈顶方向移动一个位置。
队列:
先进先出。
队列的入口、出口各占一侧。
数组:
查找元素快:
通过索引,可以快速访问指定位置的元素
增删元素慢:
指定索引位置增加元素:需要创建新数组,将指定新元素存储在指定索引位置,再把原数组元素根据索引,复制到新数组对应的索引位置。
指定索引位置删除元素:需要创建新数组,原数组中指定索引位置不复制到新数组。
链表:就是把多个节点,连接起来
节点:它是由二个部分组成。数据域(存储的数值),指针域(存储的地址)
多个节点之间,通过地址进行连接。
查找元素慢:想查找某个元素,需要通过连接的节点,依次向后查找
增删元素快:
增加元素:只需要修改连接下个元素的地址
删除元素:同理
ArrayList集合的自身特点
List接口的大小可变数组的实现。查询快,增删慢
注意:此实现不是同步的
new ArrayList() //默认是10
LinkedList
单向链
方便元素添加、删除的集合,查询慢
线程不安全
链表集合的特有功能
自身特点:链表底层实现,查询慢,增删快
子类的特有功能,不能多态调用
public class LinkedListDemo{
psvm{
}
/*
E removeFirst()
E removeLast()
*/
public static void func3(){
LinkedList<String> link = new LinkedList<String>();
link.add("abc");
link.add("bcd");
link.add("ad");
link.add("jkkk");
String first = link.removeFirst();
String last = link.removeLast();
sout(link);
}
/*
E getFirst()
E getLast()
*/
pubic static void func2(){
LinkedList<String> link = new LinkedList<String>();
link.add("abc");
link.add("bcd");
link.add("ad");
link.add("jkkk");
if(!link.isEmpty()){
String first = link.getFirst();
String last = link.getLast();
}
}
/*
addFirst(E) 添加到链表的开头
addLast(E) 添加到链表的结尾
*/
public static void func(){
LinkedList<String> link = new LinkedList<String>();
link.addLast("tingting");
link.add("abc");
link.add("bcd");
link.addFirst("terry");
}
}
Vector
可以实现可增长的对象数组。与数组一样,它包含可以使用整数索引进行访问的组件。但是,vector的大小可以根据需要增大或缩小,以适应创建vector后进行添加或移除项的操作。
线程安全,但被ArrayList代替
Set
一个不包含重复元素。通过元素的equals,来判断元素中是否有重复元素
set集合取出元素的方式可以采用:迭代器、增强for
set中的方法与父类Collection中的是一样的
HashSet
此类实现Set接口,由哈希表(实际上是一个HashMap实例)支持。他不保证set的迭代顺序。特别是他不保证该顺序恒久不变。此类允许使用null元素。
/*
Set接口,特点不重复元素,没索引
Set 接口的实现类,HashSet
特点:无序集合,存储和取出的顺序不同,没有索引,不存储重复元素
代码的编写上,和ArrayList完全一致
*/
public class HashSetDemo{
psvm{
Set<String> set = new HashSet<String>();
set.add("com");
set.add("chian");
set.add("java");
Iterator<String> it = set.iterator();
while(it.hasNext()){
sout(it.next());
}
for(String s : set){
sout(s);
}
}
}
/*
HashSet集合的自身特点:
底层数据结构:哈希表
存储,取出都比较快
线程不安全,运行速度快
*/
public class HashSetDemo1{
psvm{
HashSet<String> set = new HashSet<String>();
set.add(new String("abc"));
set.add(new String("abc"));
set.add(new String("bbc"));
set.add(new String("bbc"));
sout(set);
}
}
结果: abc bbc
现调用hashcode方法计算哈希值,判断容器内是否有相同的哈希值,没有则保存,有就调用equals方法,如果为true,后来者不保存,为false时集合判定对象没有重复,就采用桶的存储方式。
哈希表,存储对象的依据,对象的哈希值,equals
哈希表。----链表数组结合体
初始容量,数组长度默认为16,
加载因为为0.75 (数组的长度16*0.75=12)数组长度为12时,数组就会扩容,即复制!!!
称为数据的再哈希 rehash
/*
对象的哈希值,普通的十进制整数
父类Object,方法public int hashCode() 计算结果int整数
*/
public class Person(){
/*
没有做重写父类,每次运行结果都是不同整数
如果子类重写父类的方法,哈希值,自定义的
存储到HashSet集合的依据
*/
public int hashCode(){
return 1;
}
}
public class HashDemo(){
psvm{
Person p = new Person();
sout(p.hashCode());
}
}
/*
LinkedHashSet 基于链表的哈希表实现
继承自HashSet
LinkedHashSet 自身特性,具有顺序,存储和取出的顺序相同
线程不安全的集合,运行速度快
*/
public class LinkedHashSetDemo{
psvm{
LinkedHashSet<Integer> link = new LinkedHashSet<Integer>();
link.add(123);
link.add(63);
link.add(143);
link.add(23);
link.add(12);
sout(link);
}
}
/*
两个对象 Person p1 p2
问题:如果两个对象的哈希值相同p1.hashCode()==p2.hashCode()
两个对象的equlas一定返回true吗
答案:不一定
如果两个对象的equals方法返回true,
两个对象的哈希值一定相同吗
答案:一定
*/