集合:
集合是用于存储对象的一个工具。
集合与数组的特点
相同点:都是一个容器
不同点:
集合:可以存储对象,只能存储对象,集合长度可变。
数组:可以存储对象,也可以存储基本数据类型,数组长度固定。
容器对象有很多种,通过内部的数据结构来区分,数据结构就是一种数据存储方式。
在不断的将容器对象的相同点抽取的过程中,就出现了集合体系结构,该体系的结构框架称为集合框架。
最顶层的是一个接口:Collection
Collection 表示的是一组对象。
迭代器(Iterator):
Collection集合中对元素的获取方式:hasNext() 判断是否有值、next() 返回迭代的下一个元素、remover() 删除
集合容器都具备取出方式,取出方式并不是一个方法,因为一个方法并不足以完成取出,取出是由多个方法来完成的,为了方便使用,将这些方法封装称了对象;该对象在描述时,这些功能会直接使用到具体集合中的数据和集合特点。所以这个取出元素的描述类,就定义在集合的内部,也就是一个内部类。
因为这个类在直接访问集合中的数据,根据集合自身的数据结构特点,将具体的方法都定义完成后,需要将对象对外提供出去让用户使用,所以就暴露了一个方法,来完成对这个内部类对象的访问。
为了提高扩展性,发现只要是容器,就具备取出功能,但数据结构不同,取出的具体实现一样,这时为了扩展,就抽取了一个接口 Iterator (迭代器)。
Collection coll=new ArrayList();
coll.add("元素1");
coll.add("元素2");
coll.add("元素3");
Iterator iter=coll.iterator();
while(iter.haxNext()){
iter.next();
}
//或
for(Iterator iter=coll.iterator();iter.haxNext()){
iter.next();
}
View Code
只要是在 Collection 集合体系中,迭代器就是通用的取出方式。
在进行迭代器使用时,next() 在循环中只能定义一个,定义多个会导致数据错误;当next()没有获取到元素时,会发生NoSushElementException异常。
用迭代器取出自定义对象的元素时,在 next() 后要进行类型的转换操作。
Collection coll=new ArrayList();
coll.add(new ClassName("元素1"));
coll.add(new ClassName("元素2"));
coll.add(new ClassName("元素3"));
for(Iterator iter = coll.iterator(); iter.haxNext()){
ClassName cn=(ClassName)iter.next();
cn.ClassNameMethod();
}
View Code
集合List: extends Collection
该容器的元素有序,存储顺序和取出顺序一致。该集合中的元素都有索引(角标),可以存储重复的元素。
//List常见基本操作
List list=new ArrayList();
//增
list.add("元素");
list.add(1,"元素");//指定索引位插入元素,其他元素以此延续
//删
list.remover(1);//指定索引位删除元素。被删除的元素会被返回
//改
list.set(1,"New元素");//替换指定索引位元素。会返回被修改掉的元素。
//查
list.get(1);//获取索引位指定的元素。
list.indexOf("元素");//获取元素第一次出现的位置(索引)
list.subList(int,int);//根据头尾角标获取子列表,返回List集合
列表迭代器:ListIterator
在进行迭代过程中,若出现了迭代器和容器同时对元素进行操作的情况,很容易引发ConcurrentModificationException(并发修改)异常。对于List集合解决此类异常就用 ListIterator 列表迭代器
ListIterator 时 Iterator 的子接口。并提供了更多的迭代过程中的操作方法;该迭代器只能用于 List 集合。
//ListIterator 常见基本功能
List list=new ArrayList();
list.add("元素1");
list.add("元素2");
list.add("元素3");
list.add("元素4");
ListIterator lit=list.listIterator();
lit.haxNext();//判断 是否有后一个元素
lit.haxPrevious();//判断 是否有前一个元素
lit.add();//添加
lit.set();//修改
lit.next();//取后一个元素
lit.previous();//取前一个元素
ArrayList
底层数据结构是数组结构。实现不同步;jdk1.2 版本 ArrayList 替换 Vector
ArrayList 对元素的查询快,增、删 慢
判断元素是否相同时,底层的依据时 equals() 方法;无论时 contains() 还是 remover() 都会去使用 equals() 来判断元素是否相同。所以在往 ArrayList 集合中存储自定义元素时,最好建立该元素特有的判断对象是否相同的依据。也就是覆盖 equals() 方法。
Vector
底层数据结构是数组结构。实现同步;jdk1.0版本
Vector 对元素的增、删、查 都很慢
elements()方法返回枚举(Enumeration)该功能与迭代器的功能重复;由于枚举(Enumeration)书写麻烦,故被迭代器替换掉。
Vector vt=new Vector();
vt.addElement("元素1");
vt.addElement("元素2");
vt.addElement("元素3");
vt.addElement("元素4");
for(Enumeration ent=vt.elements(); ent.hasMoreElements()){
ent.nextElement();
}
可变长度数组
ArrayList 内部封装了一个默认长度为10的数组。当超出长度时,集合内部会自动生成一个新的数组;将原数组中的数据复制到新的数组中;ArrayList 新的数组长度是原数组的50%延长;Vector 新的数组长度是原数组的100%延长。
LinkedList
底层数据结构是链表结构。实现不同步;jdk1.2 版本;
LinkedList 对元素的增、删效率高,但查询慢
//特有方法
//增
addFirst();
addLast()
//获取元素,集合长度不变
getFirst();
getLast();
//jdk1.6 版本后被下面俩个方法替代。若集合中没有元素,该方法不会抛出异常,而返回null
peekFirst();
peekLast();
//获取被删除的元素,集合长度改变
removeFirst();
removeLast();
//jdk1.6 版本后被下面俩个方法替代。若集合中没有元素,该方法不会抛出异常,而返回null
offerFirst();
offerLast();
集合Set: extends Collection
该容器的元素无序;不可以重复元素。Set 接口的取出元素的方法只有迭代器。
!~ HashSet:
底层数据结构为哈希表。哈希表这种结构其实就是对哈希表的存储;而且每一个对象都有自己的哈希表。因为 Object 基类中有一个 hashCode() 方法。
存储自定义对象并且要保证元素的唯一性。HashSet 保证元素的唯一性主要依赖与 hashCode() 和 equals() 方法。
当元素的哈希值不同时,元素都有自己的独立位置,不需要再判断元素的 equals() 方法。
当元素的哈希值相同时,这时元素再哈希表中的位置相同,就需要判断一次元素的内容是否相同;调整元素的 equals() 方法进行一致比较;当这俩个元素不相同时,会存储在一个哈希值上;故、需覆盖 hashCode() 和 equals() 方法。而且需要依据对象的特有条件建立 hashCode() 和 equals() 的具体实现。
判断包含、删除都是依据 hashCode() 。当 hashCode() 相同时,再判断 equals() 方法
!~ TreeSet:
对 Set 集合中的元素进行排序。数据结构为二叉树结构;可以提高排序性能。
自定义元素本身不具备比较性,TreeSet 集合是无法对元素进行排序的。所以在自定义对象时,需要对象具备一个比较功能。而 Java 已经提供了接口,可以让自定义的对象具备比较性。需要实现 Comparable 接口。
根据比较方法 compareTo() 的返回值来确定元素的唯一性;返回0,则相同。自定义对象需要覆盖 compareTo() 方法。这称为:元素的自然排序。
如果元素本身的比较方式无法满足应用,那么 可以让集合本身具备比较性,就是定义一个类,实现 Comparator 接口,覆盖 compare() 方法。将Comparator 接口的子类对象作为参数传递给 TreeSet 集合的构造函数即可。
当元素自身具备比较性,同时 TreeSet 集合也具备比较器,这时以比较器为主。
泛型:
集合中存储了不同类型的对象,获取时,在运行时容易发生ClassCastException类型转换异常。所以在存储时明确集合要操作的数据类型来避免该异常的发生。
定义集合时,通过<>来明确元素的类型。这中定义的方式称为:泛型
优点:
1、运行时出现的ClassCastException 异常转移到编译时期。
2、泛型的出现避免了强制转换的麻烦。
泛型其实时 jdk1.5版本后出现的安全机制。
ArrayList<String> list=new ArrayList<String>();
list.add("元素");
list.add("元素1");
for(Iterator<String> iter=list.iterator();iter.hasNext()){
iter.next();
}
泛型的使用其实就是给<>传递实际参数,而这个参数就是一个具体的引用数据类型。
当类要操作的引用数据类型不确定时,可以使用泛型来定义,也就是定义一个类型参数,将具体的类型作为实际参数传递给<>
当泛型定义在类上,该泛型作用整个类。建立对象时,就明确了具体类型。那么凡是使用了类上定义的泛型的方法,操作的类也就固定了。
当类中定义 static 方法时,静态方法不可以直接访问类上的泛型;因为类上的泛型只有通过建立对象才可以明确泛型。那么静态方法若操作的引用数据类型不确定,只能将泛型定义在方法上。在静态方法上定义泛型必须定义在 static 关键字之后。
当发放中操作的应用数据类型不确定,而且和对应的对象执行的类型也不一定一致。这时就将泛型定义在方法上。
//泛型接口
interface Inter<T>{
public void method(T t);
}
泛型通配符:?
? 代表任意类型。
public static void method(Collection<?> coll){
for(Iterator<?> iter=coll.iterator(); iter.hasNext()){
iter.next();
}
}
定义T只能固定一种类型,定义 ? 可以是任意类型。
泛型限定:
? extends E 接收 E 类型 或 E 的子类型
? super E 接收 E 类型 或 E 的父类型
Map集合:
特点:
1、双列集合,Collection 是单列集合。
2、Map 一次存储一对元素,同是键值对的形式,键和值有对应关系。Collection 是一次存储一个元素。
//常见功能:
//增
put(k,v);//返回的是v;将键和值存储 Map 集合,当存入相同的 k 时,新值 v 会覆盖原来的值,并返回原来的值。
putAll(map);
//删
clear();
remove(k);//根据键删除对应的值,返回被删除的值。
//判
containsKey(Object key);
containsValue(Object value);
isEmpty();
//查
size();//获取Map 元素个数
get(k);//根据键获取值,还可以判断某个键是否存在的依据。
Collection values();//获取Map 集合中所有的值。
Set keySet();//获取Map 集合中所有的键
Set entrySet();//获取键值对的映射关系。将映射关系封装成对象存入Set 集合
Map 集合中没有迭代器,迭代器是在 Collection 集合中具备的。
Map 集合的取出元素的原理,就是将 Map 集合转成 Set 集合,再进行迭代。
HashTable:
底层是哈希表数据结构;实现同步。不允许 null 作为键、null 作为值。
Peoperties:用于配置文件的定义和操作,使用频率高,同时键和值都是字符串。是集合中可以和IO技术相结合的对象。详细见IO篇
HashMap:
底层是哈希表数据结构;实现不同步。允许 null 作为键、null 作为值。替代 HashTable
HashMap<Integer,String> hm=new HashMap<Integer,String>();
//若要保证HashMap有序。用LinkedHashMap
HashMap<Integer,String> hm=new LinkedHashMap<Integer,String>();
hm.put(1,"元素1");
hm.put(2,"元素2");
hm.put(3,"元素3");
hm.put(4,"元素4");
hm.size();//元素个数
hm.get(1);//获取键1对应的vaue
hm.remove(1);//删除键1对应的键值对
hm.clear();//清空
hm.containsKey(1);//是否包含键1
//取Map 集合中所有的键值
Set<Integer> hmKey=hm.keySet();//获取所有的键
for(Iterator<Integer> iter=hmKey.iterator(); iter.hasNext()){
Integer it=iter.next();
hm.get(it);
}
//取Map 集合中所有的键值。
Set<Map.Entry<Integer,String>> hmEntry=hm.entrySet();//获取Map 集合中所有的简直对应关系
for(Iterator<Map.Entry<Integer,String>> iter=hmEntry.iterator(); iter.hasNext()){
Map.Entry<Integer,String> me=iter.next();
Integer key=me.getKey();
String value=me.getValue();
}
TreeMap:
对Map 集合中的键进行排序。
/* 自定义集合的两种排序方式 */
//一、实现Comparable 接口。重写compareTo() 方法。
TreeMap<Student,String> tm=new TreeMap<Student,String>();
tm.put(new Student("姓名","年龄"),"Str元素");
tm.put(new Student("姓名","年龄"),"Str元素");
tm.put(new Student("姓名","年龄"),"Str元素");
Set<Student> tmkey=tm.keySet();
for(Iterator<Student> iter=tmkey.iterator(); iter.hasNext()){
Student stu=iter.next();
tm.get(stu);
}
Class Student implements Comparable<Student>{
/*
Code...
*/
public int compareTo(Student stu){
int temp=this.age-stu.age;
return temp==0?this.name.compareTo(stu.name):temp;
}
}
//二、实现Comparator 接口,重写compare() 方法。
TreeMap<Student,String> tm=new TreeMap<Student,String>(new ComparaByName());
tm.put(new Student("姓名","年龄"),"Str元素");
tm.put(new Student("姓名","年龄"),"Str元素");
tm.put(new Student("姓名","年龄"),"Str元素");
Set<Student> tmkey=tm.keySet();
for(Iterator<Student> iter=tmkey.iterator(); iter.hasNext()){
Student stu=iter.next();
tm.get(stu);
}
Class ComparaByName implements Comparator<Student>{
public int compare(Student stu1,Student stu2){
int temp=stu1.getName().compareTo(stu2.getName());
return temp==0?new Interger(stu1.getAge()).compareTo(new Integer(stu2.getAge)):temp;
}
}
集合框架工具类:
Collections、Arrays 这两个工具类中的方法都是静态的,不需要创建对象,直接使用类名调用即可。
Collections:是集合对象的工具类,提供操作集合的工具方法。
Collections.sort(List<T>);//排序,升序
Collections.sort(List<T>,Collections.reverseOrder);//排序,降序
Collections.sort(List<T>,Collections.reverseOrder(Comparator<? super T>));//指定比较器排序,降序
Collections.max();//最大值
Collections.min();//最小值
Collections.binarySearch();//二分查找(折半查找),只作用于List集合
Collections.fill(List<T>,"");//将集合中的元素替换成指定元素
Collections.reverse(List<T>);//将集合元素反转,头尾对调
Collections.swap(List<T>,int,int);//对集合中元素进行位置替换
Collections.shuffle(List<T>);//对集合中的元素进行随机位置置换
Collections.synchronizadList(List<T>);//可以将一个不同步的集合转成同步的List集合。
Arrays:是数组的工具类。提供操作数组的工具方法。
Arrays.asList(Array); 数组转成集合
当数组中的元素是引用类型的数据时,变集合后数组中的元素作为集合中的元素存在。
当数组中的元素是基本数据类型时,变集合后该数组变成集合中的元素。
在 Collection 接口中有个集合变数组的方法:toArray();
ArrayList
al.toArray(new String[al.size()]);
jdk1.5版本后,Collection 有个父接口 Iterable 。该接口的出现封装了迭代器 iterator() 方法,并提供了一个增强 for 循环。增强 for 循环只能遍历数组和 Collection 集合。简化迭代器。一般只用于遍历,而不对元素进行操作。
格式:
for(元素类型 变量:数组 或 Collection 集合){
循环体Code;
}
ArrayList<String> al=new ArrayList<String>();
al.add("元素1");
al.add("元素2");
al.add("元素3");
for(String str:al){
System.out.println(s);
}
可变参数:
在指定数据类型的后面加三个点,其实就是数组类型的参数。
格式:
void method(int... arr)
若函数上有多个参数,可变参数的位置必须是最后一个参数。否则编译失败。
静态导入:
为简化集合框架工具类 Collections 的书写,导入一个类名中所有的静态成员 import static java.util.Collections.* 然后直接使用sort()、binarySearch() 等方法来简化Collections.sort()等写法。
但是当方法名称重复时,必须要指定所属的工具类名 Arrays.toString(arr);