第八章集合
目标:
1. 掌握集合的框架
2. 掌握Collection接口
3. 掌握Iterator接口
4. 掌握List集合
5. 掌握Set集合
6. 掌握Map集合
7. 掌握Collections类
8. 了解泛型
一、 集合的框架
Java的集合是一种特别有用的工具类,它用于存储数量不等的多个对象,并且可是实现常用数据结构例如栈、堆、队列等.Java集合还可以保存具有映射关系的关联数据。Java集合大致分为三类:List、Set、Map 其中List代表有序,可重复的集合;Set代表无序,不可重复的集合;Map代表具有映射关系的集合。
集合类图结构
二、 Collection接口
Collection接口和Map接口时Java集合框架的根接口。所以Collection中拥有的方法他的子类都拥有。
Collection常用方法如下:
| |
| addAll |
| clear |
| |
| containsAll |
| |
| hashCode |
| isEmpty |
iterator | |
| |
| removeAll |
| retainAll |
| size |
| toArray |
案例:
importjava.util.*;
public classTestConnection {
public static voidmain(String[] args){
Collection c = newArrayList();//向上转型
System.out.println("西天取经人员名单如下:");
//添加元素
c.add("唐僧");
c.add("孙悟空");
c.add("猪八戒");
c.add("沙悟净");
c.add("小白龙");
System.out.println(c);
//是否包含某个元素
System.out.println("是否包含小白龙:"+c.contains("小白龙"));
//集合长度
System.out.println("西天取经人数:"+c.size());
//删除元素
c.remove("猪八戒");
System.out.println("删除后:"+c);
Collection c1 = newArrayList();
c1.add("如来佛祖");
c1.add("观世音");
c1.add("唐僧");
//添加集合
c.addAll(c1);
System.out.println("添加集合c1后:"+c);
//删除集合
c.removeAll(c1);
System.out.println("删除集合c1后:"+c);
}
}
三、 Iterator接口
Iterator接口和Collection、Map一样也是集合框架的成员,但是他和Collection、Map不一样,Collection和Map是用来存放对象的,但是Iterator是用来遍历(迭代)访问集合中的元素。Iterator也叫迭代器.
Iterator常用方法有三个:
hasNext():如果集合中还有下一个元素则返回true
next():返回集合中的下一个元素
remove():移除迭代器当前访问的元素
Iterator的使用:
1.取得迭代器
2.while(it.hasNext()){} //判断是否有元素可以遍历
3.在while循环中做操作(输出、删除)
案例一://输出ArrayList中的元素(ArrayList还可以使用for循环输出)
Iterator it = al.iterator();
while(it.hasNext()){
Dog d = (Dog) it.next();
System.out.println(d.name+"\t"+d.var+"\t"+d.age);
}
//输出HashSet的元素
Iterator it = hs.iterator();//取得hs上的迭代器
while(it.hasNext()){
Dog d = (Dog)it.next();
System.out.println(d.name+"\t"+d.var+"\t"+d.age);
}
//输出HashMap的元素
System.out.println("-------------方法一----------------");
Iterator it1 =hm.entrySet().iterator();//得到迭代器
while(it1.hasNext()){
Entry m = (Entry)it1.next();
System.out.println(m.getKey()+"-->"+m.getValue());
}
System.out.println("-------------方法二----------------");
Iterator it2 =hm.keySet().iterator();
while(it2.hasNext()){
String s = (String) it2.next();//得到键
System.out.println(s+"---->"+hm.get(s));
}
注意:使用迭代器时不可以改变集合本身(不能使用集合本身删除元素、添加元素),否则会报ConcurrentModificationException 异常,要删除使用迭代器删除
//删除叫小白的Dog
Iterator it = al.iterator();
while(it.hasNext()){
Dog d = (Dog) it.next();
if(d.name.equals("小白")){
it.remove();
}
}
四、 List接口
List代表的是有序(元素的添加顺序),可重复的集合,它常用的实现类有:ArrayList 、LinkedList
★ArrayList (List 接口的大小可变数组的实现。)
▲常用构造方法:
ArrayList |
ArrayList |
ArrayList |
▲常用方法
从Collection继承来的方法
| |
| addAll |
get | |
| |
remove |
案例一:
package test_12_4;
import java.util.*;
public class TestArrayList {
public static void main(String[] args) {
ArrayList al = new ArrayList();
al.add("A");//添加元素
al.add("B");
al.add("C");
al.add("D");
al.add("E");
al.add(0, "X");//往指定位置添加元素
System.out.println(al);
al.remove("B");//al.remove(2); 删除元素
System.out.println(al);
System.out.println(al.get(1));//取出1号位置的元素
//循环输出所有元素
for(int i = 0;i<=al.size()-1;i++){
System.out.print(al.get(i)+" ");
}
}
}
案例二:
package test5_25;
public class Dog {
public String name;//昵称
public String var;//品种
public int age;//年龄
public Dog(String name,Stringvar,int age){
this.name = name;
this.var = var;
this.age = age;
}
}
package test5_25;
import java.util.*;
public class TestArrayList2 {
public static void main(String[] args) {
Dog d1 = new Dog("小黑","贵宾狗",3);
Dog d2 = new Dog("小花","牧羊犬",2);
Dog d3 = new Dog("大黄","藏獒",2);
Dog d4 = new Dog("小白","丝毛狗",5);
Dog d5 = new Dog("小球","泰迪",2);
ArrayList al = new ArrayList();
//添加元素
al.add(d1);
al.add(d2);
al.add(d3);
al.add(d4);
al.add(d5);
//1.输出所有Dog信息
System.out.println("---------------循环输出集合中Dog信息-------------");
for(int i = 0;i<=al.size()-1;i++){
Dog d = (Dog) al.get(i);//向下转型
System.out.println(d.name+"\t"+d.var+"\t"+d.age);
}
//2.输出所有age>=3的Dog信息
System.out.println("---------------循环输出集合中age>=3的Dog信息-------------");
for(int i = 0;i<=al.size()-1;i++){
Dog d = (Dog) al.get(i);//向下转型
if(d.age>=3){
System.out.println(d.name+"\t"+d.var+"\t"+d.age);
}
}
//3.删除小白
for(int i = 0;i<=al.size()-1;i++){
Dog d = (Dog) al.get(i);
if(d.name.equals("小白")){
al.remove(i);
i--;//控制连续多个“小白”能够都被删除
}
}
System.out.println("---------------删除小白后输出Dog信息-------------");
for(int i = 0;i<=al.size()-1;i++){
Dog d = (Dog) al.get(i);//向下转型
System.out.println(d.name+"\t"+d.var+"\t"+d.age);
}
//4.查找是否存在叫小球的Dog
boolean flag = false;
for(int i = 0;i<=al.size()-1;i++){
Dog d = (Dog) al.get(i);
if(d.name.equals("小球")){
flag = true;
}
}
if(flag){
System.out.println("存在小球!");
}else{
System.out.println("不存在小球!");
}
}
}
★LinkedList (List 接口的链接列表实现。)
| addFirst |
| |
| getFirst |
| getLast |
| removeFirst |
| removeLast |
思考:
ArrayList和Linkedlist的区别
1.实现原理不一样:
ArrayList是大小可变数组的实现,内容保存在一块连续空间
LinkedList是链接列表的实现,内容保存在不连续空间
2.用途不一样
一般都是使用ArrayList,ArrayList占据内存小,查找速度快。
如果经常进行插入,删除操作可以考虑使用LinkedList
ArrayList和Vector的区别
1.Vector是一个古老的类,在JDK1.0就有,ArrayList实在JDK1.2之后才有
2.Vector有同步处理,效率低;ArrayList使用异步处理,性能高
3.Vector是线程安全的,ArrayList是线程不安全的。
五、 Set接口
Set代表的是无序,不可重复的集合,它常用的实现类有:HashSet
★HashSet (此类实现 Set 接口,由哈希表(实际上是一个 HashMap 实例)支持)
HashSet特点:
1. 不能保证元素的顺序,每个元素的顺序可能随时变化
2. HashSet不同步
3. HashSet中可以放值为null的元素
当往HashSet中添加元素时,HashSet会调用该对象的hashCode()方法取得该对象的hashCode值,再根据该对象的hashCode值来决定该对象在HashSet中的存放位置。如果两个对象通过equals比较返回值为true,但是如果他们的hashCode值不一样,这样HashSet会根据他们的hashCode值将两个元素存放在不同位置。
总结:HashSet判断两个元素相等必须满足两个条件1.equals()方法返回true 2.hashCode()方法返回值相等
▲常用构造方法:
HashSet |
HashSet |
HashSet |
HashSet |
▲常用方法:
从Collection继承来的方法
案例一:
package test_12_4;
import java.util.*;
public class TestHashSet {
public static void main(String[] args) {
HashSet hs = new HashSet();
hs.add("A");//添加元素
hs.add("B");
hs.add("C");
hs.add("D");
hs.add("E");
hs.add("B");//无法添加成功,因为Set集合无序不可重复
System.out.println(hs);//
}
}
案例二:(如果两个Dog的name、var、age一样就说它相等,无法添加进入)
public class Dog {
public String name;
public String var;
public int age;
public Dog(String name,String var,int age){
this.name = name;
this.var = var;
this.age = age;
}
//重写Object类的equals方法
//Object中equals方法是比较两个对象的地址
public boolean equals(Object obj) {
boolean flag =false;
Dog d = (Dog)obj;
if(this.name.equals(d.name)&&this.var.equals(d.var)&&this.age==d.age){
flag = true;
}
return flag;
}
//重写Object类的hashCode方法
public int hashCode() {
return this.name.hashCode();
}
}
import java.util.*;
public class TestHashSet2 {
public static void main(String[] args) {
Dog d1 = new Dog("小黑","贵宾狗",3);
Dog d2 = new Dog("小花","牧羊犬",2);
Dog d3 = new Dog("大黄","藏獒",2);
Dog d4 = new Dog("小白","丝毛狗",5);
Dog d5 = new Dog("小球","泰迪",2);
Dog d6 = new Dog("小球","泰迪",2);
HashSet hs = new HashSet();
//添加元素
hs.add(d1);
hs.add(d2);
hs.add(d3);
hs.add(d4);
hs.add(d5);
hs.add(d6);
//输出
Iterator it = hs.iterator();//取得hs上的迭代器
while(it.hasNext()){
Dog d = (Dog)it.next();
System.out.println(d.name+"\t"+d.var+"\t"+d.age);
}
}
}
六、 Map接口
Map用来保存具有映射关系的数据,因此该集合中保存着两组值,一组用来保存Map的键(Key),一组用来保存Map中的值(value)。Key和value是一对一关系,可以通过指定的键找到唯一的一个value。Map中键在一起就组成Set集合,值在一起就组成List集合。
★HashMap (基于哈希表的 Map 接口的实现。)
▲常用构造方法:
HashMap() 构造一个具有默认初始容量 (16) 和默认加载因子 (0.75) 的空 HashMap。 |
HashMap(int initialCapacity) 构造一个带指定初始容量和默认加载因子 (0.75) 的空 HashMap。 |
HashMap(int initialCapacity, float loadFactor) 构造一个带指定初始容量和加载因子的空 HashMap。 |
HashMap(Map<? extends K,? extends V> m) 构造一个映射关系与指定 Map 相同的新 HashMap。 |
▲常用方法:
void | clear() 从此映射中移除所有映射关系(可选操作)。 |
boolean | containsKey(Object key) 如果此映射包含指定键的映射关系,则返回 true。 |
boolean | containsValue(Object value) 如果此映射将一个或多个键映射到指定值,则返回 true。 |
boolean | |
boolean | isEmpty() 如果此映射未包含键-值映射关系,则返回 true。 |
Object | |
void | |
int | size() 返回此映射中的键-值映射关系数。 |
values() 返回此映射中包含的值的 Collection 视图。 |
案例 :
package test_12_8;
import java.util.*;
import java.util.Map.Entry;
public class TestHashMap {
public static void main(String[] args) {
HashMap hm = new HashMap();
hm.put("CN", "中国");//往HashMap中添加值(键值对)
hm.put("US", "美国");
hm.put("RU", "俄罗斯");
hm.put("JP", "小日本");
System.out.println(hm);
System.out.println("hasMap中键值对个数="+hm.size());
System.out.println("CN对应:"+hm.get("CN"));//通过制定的Key取得对应的值
hm.remove("JP");//通过键删除制定的键值对
System.out.println("输出键值对:"+hm);
System.out.println("输出所有键:"+hm.keySet());
System.out.println("输出所有值:"+hm.values());
//循环输出HashMap中的元素
System.out.println("-------------方法一----------------");
Iterator it1 =hm.entrySet().iterator();//得到迭代器
while(it1.hasNext()){
Entry m = (Entry)it1.next();
System.out.println(m.getKey()+"-->"+m.getValue());
}
System.out.println("-------------方法二----------------");
Iterator it2 =hm.keySet().iterator();
while(it2.hasNext()){
String s = (String) it2.next();
System.out.println(s+"---->"+hm.get(s));
}
}
}
七、Collections类
Collections类是用来对Collection进行操作的一个类。
package test_12_8;
import java.util.*;
public class Test {
public static void main(String[] args) {
ArrayList al = new ArrayList();
al.add(10);
al.add(8);
al.add(15);
al.add(9);
System.out.println("集合:"+al);
Collections.reverse(al);
System.out.println("集合:"+al);
System.out.println("最大值:"+Collections.max(al));
System.out.println("最小值:"+Collections.min(al));
Collections.sort(al);
System.out.println("排序后:"+al);
}
}
八、泛型
在前面的案例中,往集合中添加Dog,每次取出集合中的元素需要强制转换成Dog,非常麻烦,此时可以使用泛型解决.
没有使用泛型
public class TestArrayList2 {
public static void main(String[] args) {
Dog d1 = new Dog("小黑","贵宾狗",3);
Dog d2 = new Dog("小花","牧羊犬",2);
Dog d3 = new Dog("大黄","藏獒",2);
Dog d4 = new Dog("小白","丝毛狗",5);
Dogd5 = new Dog("小球","泰迪",2);
ArrayList al = new ArrayList();
//添加元素
al.add(d1);
al.add(d2);
al.add(d3);
al.add(d4);
al.add(d5);
for(int i =0;i<=al.size()-1;i++){
Dog d = (Dog) al.get(i);//向下转型
System.out.println(d.name+"\t"+d.var+"\t"+d.age);
}
}
}
使用泛型
package test_12_8;
import java.util.*;
public class TestArrayList2 {
public static void main(String[] args) {
Dog d1 = new Dog("小黑","贵宾狗",3);
Dog d2 = new Dog("小花","牧羊犬",2);
Dog d3 = new Dog("大黄","藏獒",2);
Dog d4 = new Dog("小白","丝毛狗",5);
Dog d5 = new Dog("小球","泰迪",2);
ArrayList<Dog> al = new ArrayList<Dog>();//使用泛型
//ArrayList<Dog> al= new ArrayList();//使用泛型
//添加元素
al.add(d1);
al.add(d2);
al.add(d3);
al.add(d4);
al.add(d5);
al.add("ABC");//报错,前面指定集合为Dog类型,所以只能添加Dog对象
for(int i =0;i<=al.size()-1;i++){
Dog d = al.get(i);//向下转型
System.out.println(d.name+"\t"+d.var+"\t"+d.age);
}
}
}