-------android培训、java培训、期待与您交流! ----------
一 集合类概述
(1)为什么出现集合类?
面向对象对事物的体现都是以对象的形式,为了方便对多个对象的操作,就对对象进行存储。
集合就是存储对象最常用的一种方式.
(2)数组和集合都是容器,两者有何不同?
数组长度固定,而集合长度是可变的
数组值可以存储对象,还可以存储基本数据类型;而集合只能存储对象
数组存储数据类型是固定的,而集合存储的数据类型不固定
(3)集合类的特点:
集合只能存储对象
集合的长度是可变的
集合可以存储不同类型的对象
二 集合类框架
(一)集合框架的构成及分
(二)集合类容器
ⅠCollection 顶层接口
(1)List:列表,元素是有序的(元素带角标索引),可以有重复元素,可以有null 元素
①ArrayList(JDK1.2):底层的数据结构是数组数据结构,特点是查询速度快(因 为带角标),但是增删速度稍慢,因为当元素多时,增删一个元素则所有元素的角标都得改变,线程不同步。默认长度是10,当超过长度时,按50%延长集合长度。
②LinkedList(JDK1.2):底层数据结构式链表数据结构(即后面一个元素记录前一个),特点:查询速度慢,因为每个元素只知道前面一个元素,但增删速度快,因为元素再多,增删一个,只要让其前后的元素重新相连即可,线程是不同步的。
③Vector(JDK1.0):底层数据结构是数组数据结构.特点是查询和增删速度都很慢。默认长度是10,当超过长度时,按100%延长集合长度。线程同步。(Vector功能跟ArrayList功能一模一样,已被ArrayList替代)。
List集合使用注意事项:
①ArrayList:
1)当往ArrayList里面存入元素没什么要求时,即只要求有序就行时;
2)当往ArrayList里面存入元素要求不重复时,比如存入学生对象,当同名同姓时视为同一个人,则不往里面存储。则定义学生对象时,需复写equals方法,保证元素的唯一性。
public boolean equals(Object obj) { if(!(obj instanceof Student)) return false; Student stu = (Student)obj; return this.name.equals(stu.name)&&this.age==stu.age; }
则往ArrayList集合通过add存入学生对象时,集合底层自己会调用学生类的equals方法,判断重复学生则不存入。
注:对于List集合,无论是add、contains、还是remove方法,判断元素是否相同,都是通过复写equals方法来判断!
import java.util.*; /* 将自定义对象做为元素存到ArrayList集合中,并去除重复元素 */ class ArrayListTest2 { public static void sop(Object obj) { System.out.println(obj); } public static void main(String[] args) { ArrayList al = new ArrayList(); al.add(new Person("lisi01",30));//al.add(Object obj);//Object obj = new Person("lisi01",30); al.add(new Person("lisi02",31)); al.add(new Person("lisi03",32)); al.add(new Person("lisi02",31)); al.add(new Person("lisi03",32)); al.add(new Person("lisi04",33)); //删除重复的元素 al = singleElement(al); //删除 sop("remove 03 : "+al.remove(new Person("Lisi03",33))); //迭代 Iterator it = al.iterator(); while(it.hasNext()) { Person p = (Person)it.next();//需要类型一致,要做强转 sop(p.getName()+"::"+p.getAge()); } } public static ArrayList singleElement(ArrayList al) { //定义一个临时容器 ArrayList newAl = new ArrayList(); Iterator it = al.iterator(); while (it.hasNext()) { Object obj = it.next(); if (!newAl.contains(obj)) newAl.add(obj); } return newAl; } } class Person { private String name; private int age; Person(String name,int age) { this.name = name; this.age = age; } //重写equals,List集合判断元素是否相同,依据的是元素的equals方法 public boolean equals(Object obj) { if (!(obj instanceof Person)) return false; Person p = (Person)obj; System.out.println(this.name+"..."+p.name); return this.name.equals(p.name)&&this.age==p.age; } public String getName() { return name; } public int getAge() { return age; } }
②LinkedList
1)LinkLedist的特有方法:
boolean offerFirst(E e) 在此列表的开头插入指定的元素。
boolean offerLast(E e) 在此列表末尾插入指定的元素。
E peekFirst() 获取但不移除此列表的第一个元素;如果此列表为空,则返回 null。
E peekLast() 获取但不移除此列表的最后一个元素;如果此列表为空,则返回 null。
E pollFirst() 获取并移除此列表的第一个元素;如果此列表为空,则返回 null。
E pollLast() 获取并移除此列表的最后一个元素;如果此列表为空,则返回 null。
2)通过LinkLedist的特有方法,可以实现某些数据特殊方式的存取,比如堆栈和队列。
③一般情况下,使用哪种List接口下的实现类呢?
如果要求增删快,考虑使用LinkedList
如果要求查询快,考虑使用ArrayList
如果要求线程安全,考虑使用Vector。
(2)Set:集合,元素是无序的(因为没有索引),元素不可以重复。可以有null元素。
①HashSet(JDK1.2):底层数据结构是哈希表、存取速度快、元素唯一、线程不同步。保证性元素唯一的原理:
先判断元素的hashCode值是否相同,再判断两元素的equals方法是否为true(往HashSet里面存的自 定义元素要复写hashCode和equals方法,以保证元素的唯一性!)
②TreeSet:底层数据结构式二叉树。可以对Set集合中的元素进行排序。元素有序、线程不同步。 保证元素唯一性的依据:compareTo方法return 0
TreeSet排序的第一种方式:
让元素自身具备比较性,实现Compareble接口,覆盖compareTo方法,此方式是元素的自然顺序
TreeSet排序的第二种方式:
当元素自身不具备比较性(比如存储学生对象时)或者具备的比较性不是我们所需要的比较性时(比如想字符串的长度排序),此时就需要让集合自身具备自定义的比较性。 那如何让集合自身具备比较性呢?可在集合初始化时,就让集合具备比较方式。即定义一个类,实现Comparator接口,覆盖compare方法。
Set集合使用注意事项:
①HashSet:
通过new的方式往HashSet里面存的元素的hashCode都不同,但通常我们定义对象,比如学生对象时,虽然是new的两个学生对象,但是当他们name和age一样时,我们认为是同一个对象,所以为了保证元素的唯一性,我们通常在往HashSet集合里面存储元素时,在定义对象的类中通常复写hashCode和equals方法。
public int hashCode() { return name.hashCode()+age*39; } public boolean equals(Object obj) { if(!(obj instanceof Student)) return false; Student stu = (Student)obj; return this.name.equals(stu.name)&&this.age==stu.age; }
HashSet是如何保证元素唯一性的呢?
**如果两元素的hashCode值不同,则不会调用equals方法
**如果两元素的hashCode值相同,则继续判断equals是否返回true;
**hashCode和equals方法虽然定义在自定义对象类里面,但不是我们手动调用
而是往HashSet集合里面存储元素的时候,集合底层自己调用hashCode
和equals它自己拿对象去判断,自己判断两元素是否是同一个元素。
import java.util.*; /* 往HashSet集合中存入自定义元素,性名和年龄相同为同一个人,为重复元素 */ class HashSetTest { public static void sop(Object obj) { System.out.println(obj); } public static void main(String[] args) { HashSet hs = new HashSet(); hs.add(new Person("a1",11));//al.add(Object obj);//Object obj = new Person("a1",11); hs.add(new Person("a2",12)); hs.add(new Person("a3",13)); hs.add(new Person("a4",14)); hs.add(new Person("a3",13)); hs.add(new Person("a4",14)); //判断 sop("al:"+hs.contains(new Person("a2",12))); //删除 hs.remove(new Person("a4",13)); //迭代 Iterator it = hs.iterator(); while(it.hasNext()) { Person p = (Person)it.next();//需要类型一致,要做强转 sop(p.getName()+"::"+p.getAge()); } } } class Person { private String name; private int age; Person(String name,int age) { this.name = name; this.age = age; } //覆盖hashCode方法 public int hashCode() { System.out.println(this.name+".....hashCode"); return name.hashCode()+age*34; } //重写equals方法 public boolean equals(Object obj) { if (!(obj instanceof Person)) return false; Person p = (Person)obj; System.out.println(this.name+"..equals.."+p.name); return this.name.equals(p.name)&&this.age==p.age; } public String getName() { return name; } public int getAge() { return age; } }
②TreeSet:
TreeSet要求往里面存的元素具备比较性,否则会报错。
TreeSet排序的第一种方式:
让元素自身具备比较性,定义对象类,实现Compareble接口,复写compareTo方法,此方式是元素的自然顺序
class Student implements Comparable { private String name; private int age; public Student(String name,int age) { this.name=name; this.age=age; } public String getName() { return name; } public int getAge() { return age; } public int compareTo(Object obj) { if(!(obj instanceof Student)) throw new RuntimeException("不是学生对象!"); Student stu = (Student)obj; int num = this.age-stu.age; if(num==0) return this.name.compareTo(stu.name); return num; } }
TreeSet排序的第二种方式:
让集合具备比较性当元素自身不具备比较性(比如存储学生对象时)或者具备的比较性不是我们所需要的比较性时(比如想字符串的长度排序),此时就需要让集合自身具备自定义的比较性。 那如何让集合自身具备比较性呢?可在集合初始化时,就让集合具备比较方式。即定义一个类,实现Comparator接口,覆盖compare方法。
class StringLengthComparator implements Comparator { public int compare(Object obj1,Object obj2) { String s1 = (String)obj1; String s2 = (String)obj2; int num = new Integer(s1.length()).compareTo(new Integer(s2.length())); if(num==0) return s1.compareTo(s2); return num; } } class TreeSetTest { public static void main(String[] args) { TreeSet ts = new TreeSet(new StringLengthComparator()); ts.add("addfg"); ts.add("dfg"); ts.add("agtuug"); ts.add("vgjkg"); sop(ts); } } 注意:基本数据类型或字符串对象均实现了Comparable接口,故同种类型基本数据间具备比较性,即自然顺序。
Ⅱ Map 顶层接口
该集合存储的是键值对,而且键是唯一的,Map和Set很像,Set集合底层就是使用了Map集合。
Map集合没有迭代器,要取出元素必须先将Map集合转换成Set集合才能遍历元素
⑴HashTable(JDK1.0):底层是哈希表数据结构;不可以使用null键和null值;用作键的对象必须实现hashCode和equals方法来保证键的唯一性,线程同步,效率低
(2)HashMap(JDK1.2):底层是哈希表数据结构;允许使用null键和null值;线程不同步,效率高;保证元素唯一性的原理:先判断元素的hashCode值是否相同,再判断两元素的equals方法是否为true(往HashSet里面存的自定义元素要复写hashCode和equals方法,以保证元素的唯一性!)
class Student { private String name; private int age; public Student(String name, int age) { super(); this.name = name; this.age = age; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public int hashCode(){ return name.hashCode()+age*34; } @Override public boolean equals(Object obj){ if(!(obj instanceof Student)) return false; Student stu = (Student)obj; return this.name.equals(stu.name)&&this.age==stu.age; } public class HashMapDemo1 { public static void main(String[] args) { Map<Student , String> hmap = new HashMap<Student , String>(); hmap.put(new Student("001",20), "beijing"); hmap.put(new Student("002",25), "hebei"); hmap.put(new Student("003",50), "hainan"); hmap.put(new Student("001",20), "beijing"); System.out.println(hmap.size()); Set<Student> keySet = hmap.keySet(); Iterator<Student> it = keySet.iterator(); while(it.hasNext()){ Student stu = it.next(); String addr = hmap.get(stu); System.out.println(stu.getName()+".."+stu.getAge()+"::"+addr); } } }
(3)TreeMap(JDK1.0):底层是二叉树结构;允许使用null键和null值;线程不同步;可以给Map集合中的键进行排序.
TreeMap排序的第一种方式:
让元素自身具备比较性,实现Compareble接口,覆盖compareTo方法,此方式是元素的自然顺序
TreeMap排序的第二种方式:
让集合具备比较性当元素自身不具备比较性(比如存储学生对象时)或者具备的比较性不是我们所需要的比较性时(比如想字符串的长度排序),此时就需要让集合自身具备自定义的比较性。 那如何让集合自身具备比较性呢?可在集合初始化时,就让集合具备比较方式。即定义一个类,实现Comparator接口,覆盖compare方法。
class Student implements Comparable<Student>{
private String name;
private int age;
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int compareTo(Student stu) {
int num = new Integer(this.age).compareTo(new Integer(stu.age));
if(num==0)
return this.name.compareTo(stu.name);
return num;
}
}
public class HashMapDemo1 {
public static void main(String[] args) {
Map<Student , String> tmap = new TreeMap<Student , String>();
tmap.put(new Student("001",20), "beijing");
tmap.put(new Student("002",25), "hebei");
tmap.put(new Student("003",50), "hainan");
tmap.put(new Student("001",20), "beijing");
System.out.println(tmap.size());
//hashMap的第一种取出方式 keySet
Set<Student> keySet1 = tmap.keySet();
Iterator<Student> it1 = keySet1.iterator();
while(it1.hasNext()){
Student stu = it1.next();
String addr = tmap.get(stu);
System.out.println(stu.getName()+".."+stu.getAge()+"::"+addr);
}
/*
//hashMap的第二种取出方式 entrySet
Set<Map.Entry<Student,String>> entrySet = hm.entrySet();
Iterator<Map.Entry<Student,String>> ite = entrySet.iterator();
while(ite.hasNext())
{
Map.Entry<Student,String> me = ite.next();
Student stu = me.getKey();
String addr = me.getValue();
System.out.println(stu+"\\\\"+addr);
}
*/
}
}
(三)集合类各容器方法
1接口Collection方法摘要(没有构造方法)
a)添加:
boolean add(E e)
boolean addAll(Collection c)
b)删除:
void clear():清空容器
boolean remove(Objec object):
boolean removeAll(Collection c):
c)判断:
boolean contains(Object object):判断是否包含此元素
boolean containsAll(Collection c):判断是否包含一堆元素
boolean equals(Object object):比较此collection与指定对象是否相等
boolean isEmpty():判断是否集合为空
d)获取:
Iterator iterator():取出
Iterator it = al.iterator();
While(it.hasNext())
{
System.out.println(“next:”+it.next());
}
int hashCode():返回此collection的哈希值
int size():返回此collection中元素的个数
boolean retainAll(Collection c):取交集
Object toArray():返回此collection中所有元素的数组
T[] toArray(T[] a):返回包含此collection中所有元素的数值。
2 List集合子类及其方法
(1)List接口是Collection接口的一个子接口。
(2)List接口中的元素有如下特点(对角标的操作都是特有方法,因为有序):
A:元素有序(存储顺序和取出顺序一致)
B:元素可以重复
(3)List接口中的特有方法
add(int index,Object obj):在指定位置加入元素
remove(int index):移除指定位置的元素
set(int index,Object obj):修改指定位置的元素
get(int index):获取指定位置的元素
indexOf(Object obj):获取指定元素的位置
subList(int start,int end):从一个大的List中截取一个小的List
listIterator():返回一个List接口特有的迭代器
ListIterator it = al.ListIterator();
while(it.hasNext())
{
Object obj = it.next();
if(ibj.equals(“java02”))
it.add(“java03”);
}
while(it.hasPrevious())
{
System.out.println(“pre:”+it.previous());
}
(4)List接口中子类及其方法
1)ArrayList:
|--->构造方法摘要:(少用,不是重点)
ArrayList():构造一个初始容量为 10 的空列表。
ArrayList(Collection<? extends E> c): 构造一个包含指定 collection 的元素的列表,
ArrayList(int initialCapacity): 构造一个具有指定初始容量的空列表
|--->方法摘要:
a)添加:
boolean add(E e): 将指定的元素添加到此列表的尾部。
void add(int index, E element): 将指定的元素插入此列表中的指定位置。
boolean addAll(Collection<? extends E> c):按照指定 collection 的迭代器所返回的元素顺序,
将该 collection 中的所有元素添加到此列表的尾部
boolean addAll(int index, Collection<? extends E> c): 从指定的位置开始,将指定 collection
中的所有元素插入到此列表中。
b)删除:
void clear(): 移除此列表中的所有元素。
E remove(int index): 移除此列表中指定位置上的元素。
boolean remove(Object o): 移除此列表中首次出现的指定元素(如果存在)。
protected void removeRange(int fromIndex, int toIndex): 移除列表中索引在 fromIndex(包括)
和 toIndex(不包括)之间的所有元素。
boolean removeAll(Collection<?> c): 从列表中移除指定 collection 中包含的其所有元素
c)获取:
E get(int index): 返回此列表中指定位置上的元素。
For(int x=0;x<al.size();x++)
{
System.out.println(“al(”+x+”)=”+al.get(x));
}
int indexOf(Object o): 返回此列表中首次出现的指定元素的索引,或如果此列表不包含元素,
则返回 -1。
int lastIndexOf(Object o) 返回此列表中最后一次出现的指定元素的索引,或如果此列表不包含
索引,则返回 -1。
public List<E> subList(int fromIndex,int toIndex): 返回列表中指定的 fromIndex(包括 ) 和 toIndex(不包括)之间的部分视图。
Iterator<E> iterator(): 返回按适当顺序在列表的元素上进行迭代的迭代器。
ListIterator<E> listIterator(int index):返回列表中元素的列表迭代器(按适当顺序)从列表的指定位置
开始。
d)修改:(特有方法!!)
E set(int index, E element): 用指定的元素替代此列表中指定位置上的元素。
(2)LinkedList:
|--->构造方法摘要:
LinkedList(): 构造一个空列表。
LinkedList(Collection<? extends E> c): 构造一个包含指定 collection 中的元素的列表,
这些元素按其 collection 的迭代器返回的顺序排列。
|--->方法摘要:(特有的)
a)添加
void addFirst(E e): 将指定元素插入此列表的开头。
void addLast(E e): 将指定元素添加到此列表的结尾。
a)获取元素,但不删除元素
E get(int index): 返回此列表中指定位置处的元素。
E getFirst(): 返回此列表的第一个元素。
E getLast(): 返回此列表的最后一个元素。
c)获取元素且删除元素
E remove(): 获取并移除此列表的头(第一个元素)。
E remove(int index): 移除此列表中指定位置处的元素。
boolean remove(Object o): 从此列表中移除首次出现的指定元素(如果存在)。
E removeFirst(): 移除并返回此列表的第一个元素。
E removeLast(): 移除并返回此列表的最后一个元素。
d)修改
E set(int index, E element) 将此列表中指定位置的元素替换为指定的元素。
(3)Vector
|--->构造方法摘要:
Vector(): 构造一个空向量,使其内部数据数组的大小为 10,其标准容量增量为零。
Vector(Collection<? extends E> c): 构造一个包含指定 collection 中的元素的向量,
这些元素按其 collection 的迭代器返回元素的顺序排列。
|--->方法摘要:
a)添加:
boolean add(E e): 将指定元素添加到此向量的末尾。
void add(int index, E element): 在此向量的指定位置插入指定的元素。
boolean addAll(Collection<? extends E> c):
将指定 Collection 中的所有元素添加到此向量的末尾,
按照指定 collection 的迭代器所返回的顺序添加这些元素。
boolean addAll(int index, Collection<? extends E> c): 在指定位置将指定 Collection 中的
所有元素插入到此向量中。
b)获取:
Enumeration<E> elements(): 返回此向量的组件的枚举。
Vector特有的取出方式:
枚举和迭代器很像,其实枚举和迭代器是一样的,只是因为枚举的名称和方法的名称
名字都过长,所以枚举被迭代器取代了。
枚举Enumeration的方法摘要:
boolean hasMoreElements(): 测试此枚举是否包含更多的元素。
E nextElement(): 如果此枚举对象至少还有一个可提供的元素,则返回此枚举的下
一 个元素。
3 Set集合子类及其方法
(1)HashSet:它不保证set的迭代顺序;特别是它不保证该顺序恒久不变.此类允许使用null元素。
|--->构造方法:
HashSet() 构造一个新的空 set,其底层 HashMap 实例的默认初始容量是16,加载因子是 0.75。
HashSet(Collection<? extends E> c) 构造一个包含指定 collection 中的元素的新 set。
|--->方法摘要:
boolean add(E e) 如果此 set 中尚未包含指定元素,则添加指定元素。
void clear() 从此 set 中移除所有元素。
Object clone() 返回此 HashSet 实例的浅表副本:并没有复制这些元素本身。
boolean contains(Object o) 如果此 set 包含指定元素,则返回 true。
boolean isEmpty() 如果此 set 不包含任何元素,则返回 true。
Iterator<E> iterator() 返回对此 set 中元素进行迭代的迭代器。
boolean remove(Object o) 如果指定元素存在于此 set 中,则将其移除。
int size() 返回此 set 中的元素的数量(set 的容量)。
(2)TreeSet:使用元素的自然顺序对元素进行排序,或者根据创建 set 时提供的 Comparator 进行排序.
|--->构造方法:
TreeSet() 构造一个新的空 set,该set根据其元素的自然顺序进行排序。
TreeSet(Collection<? extends E> c) 构造一个包含指定 collection 元素的新 TreeSet,
它按照其元素的自然顺序进行排序。
TreeSet(Comparator<? super E> comparator)构造一个新的空TreeSet它根据指定比较器进行排序。
|--->方法摘要:
a)添加:
boolean add(E e) 将指定的元素添加到此 set(如果该元素尚未存在于 set 中)。
boolean addAll(Collection<? extends E> c) 将指定 collection 中的所有元素添加到此 set 中。
b)删除:
void clear() 移除此 set 中的所有元素。
boolean remove(Object o) 将指定的元素从 set 中移除(如果该元素存在于此 set 中)。
E pollFirst() 获取并移除第一个(最低)元素;如果此 set 为空,则返回 null。
E pollLast() 获取并移除最后一个(最高)元素;如果此 set 为空,则返回 null。
c)获取:
Iterator<E> iterator() 返回在此 set 中的元素上按升序进行迭代的迭代器。
E first() 返回此 set 中当前第一个(最低)元素。
E last() 返回此 set 中当前最后一个(最高)元素。
int size() 返回 set 中的元素数(set 的容量)。
d)判断:
boolean isEmpty() 如果此 set 不包含任何元素,则返回 true。
boolean contains(Object o) 如果此 set 包含指定的元素,则返回 true。
4 Map集合方法
|--->方法摘要:
a)添加:
V put(K key, V value) 将指定的值与此映射中的指定键关联(可选操作)。
void putAll(Map<? extends K,? extends V> m) 从指定映射中将所有映射关系复制到此映射中
b)删除:
void clear() 从此映射中移除所有映射关系(可选操作)。
V remove(Object key) 如果存在一个键的映射关系,则将其从此映射中移除(可选操作)。
c)判断
boolean containsKey(Object key) 如果此映射包含指定键的映射关系,则返回 true。
boolean containsValue(Object value) 如果此映射将一个或多个键映射到指定值,则返回 true。
boolean isEmpty() 如果此映射未包含键-值映射关系,则返回 true。
d)获取
int size() 返回此映射中的键-值映射关系数。
Collection<V> values() 返回此映射中包含的值的 Collection 视图。
Map集合没有迭代器,以下是Map的两种取出方式:
第一种:Set<K> keySet()
返回此映射中包含的键的Set视图,将Map集合中所有的键存入Set集合,然后再通过Set集合的
迭代器取出所有的键,再根据get方法获取每个键的值;
第二种:Set<Map.Entry<K,V>> entrySet()
返回此映射中包含的映射关系的Set视图,将Map集合中的映射关系存入到Set集合中,
这个映射关系的数据类型是Map.entry,再通过Map.Entry类的方法再要取出关系里面的键和值
Map.Entry的方法摘要:
boolean equals(Object o) 比较指定对象与此项的相等性。
K getKey() 返回与此项对应的键。
V getValue() 返回与此项对应的值。
int hashCode() 返回此映射项的哈希码值。
V setValue(V value) 用指定的值替换与此项对应的值(特有!!!)。
import java.util.*; class MapDemo { public static void main(String[] args) { Map<String,String> map = new HashMap<String,String>(); //添加 map.put("01","zhangshan1"); map.put("01","zhangshan4");//添加的时候,如果出现相同的建,那么后添加的值会覆盖原有建对应 //的值,并put方法会返回被覆盖的值 map.put("02","zhangshan2"); map.put("03","zhangshan3"); /* //打印 System.out.println(map); //判断 System.out.println("containsKey:"+map.containsKey("02")); //获取 System.out.println("get:"+map.get("02")); 注意://可以通过get方法的返回值来判断一个键是否存在,通过返回null来判断 map.put("04",null); System.out.println("get:"+map.get("04")); //获取map集合中的所有值 Collection<String> coll = map.values(); System.out.println(coll); //删除 System.out.println("remove:"+map.remove("02")); */ /*keySet*/ //先获取map集合的所有键的Set集合,keySet(); Set<String> keySet = map.keySet(); //有了Set集合,就可以获取其迭代器 Iterator<String> it = keySet.iterator(); while (it.hasNext()) { String s = it.next(); //有了键就可以通过map集合的get方法获取其对应的值 String value = map.get(s); System.out.println("key:"+s+",value:"+value); } /*entrySet //将Map集合中的映射关系取出,存入到Set集合中 Set<Map.Entry<String,String>> entrySet = map.entrySet(); Iterator<Map.Entry<String,String>> it = entrySet.iterator(); while (it.hasNext()) { Map.Entry<String,String> me = it.next(); String key = me.getKey(); String value = me.getValue(); System.out.println("key:"+key+",value:"+value); } */ } }
(四)Map集合和Collection集合的区别
1, Map中一次存储是键值对。
Collection中一次存储是单个元素。
2, Map的存储使用的put方法。
Collection存储使用的是add方法。
3, Map集合没有迭代器,Map的取出,是将Map转成Set,在使用迭代器取出。
Collection取出,使用就是迭代器。
4, 如果对象很多,必须使用集合存储。
如果元素存在着映射关系,可以优先考虑使用Map存储或者用数组,
如果没有映射关系,可以使用Collection存储。
(五)迭代器与迭代列表
1)迭代器:Iterator(Map集合没有迭代器)
(1)迭代器就是取出集合元素的方式
(2)迭代器的作用
因为每个集合中元素的取出方式都不一样,于是就把元素的取出方式进行抽取,并定义在集合内部,
这样取出方式就可以直接访问集合内部的元素;
而每个容器的数据结构不同,所以取出动作的细节也不一样,但是有共性内容:判断和取出。
那么就将共性内容进行抽取,从而形成了接口Iterater
(3)获取迭代器的方法:
Iterator<E> iterator() 返回在此 collection 的元素上进行迭代的迭代器。
Iterator<E> iterator() 返回在此 set 中的元素上进行迭代的迭代器。
(3)迭代器方法:
boolean hasNext() 如果仍有元素可以迭代,则返回 true。
E next() 返回迭代的下一个元素。
void remove() 从迭代器指向的collection中移除迭代器返回的最后一个元素(可选操作)。
Iterator<Person> it = al.iterator();
while(it.hasNext())
{
Person p = it.next();
sop(p.getName()+"::"+p.getAge());
}
2)列表迭代器:(List集合特有的迭代器)ListIterator
(1)List集合特有的迭代器ListIterator是Iterator的子接口,在迭代时,不可以通过集合对象的
方法操作集合中的元素,因为会发生ConcurrentModificationException(当方法检测到对象的并发修改,
但不允许这种修改时,抛出此异常)
(2)Iterator方法有限,只能对元素进行判断、取出和删除的操作
ListIterator可以对元素进行添加和修改动作等。
(3)获取列表迭代器方法:
ListIterator<E> listIterator() 返回此列表元素的列表迭代器(按适当顺序)。
ListIterator<E> listIterator(int index)
返回此列表中的元素的列表迭代器(按适当顺序),从列表中指定位置开始。
(4)列表迭代器方法:
void add(E e) 将指定的元素插入列表(可选操作)。
boolean hasPrevious() 如果以逆向遍历列表,列表迭代器有多个元素,则返回 true。
int nextIndex() 返回对 next 的后续调用所返回元素的索引。
E previous() 返回列表中的前一个元素。
int previousIndex() 返回对 previous 的后续调用所返回元素的索引。
void set(E e) 用指定元素替换 next 或 previous 返回的最后一个元素(可选操作)。
public static void listIterator() { ArrayList al = ArrayList(); al.add(“java01”); al.add(“java04”); ListIterator it = al.ListIterator(); while(it.hasNext())//向前遍历 { Object obj = it.next(); if(ibj.equals(“java02”)) it.add(“java03”); } while(it.hasPrevious())//向后遍历 { System.out.println(“pre:”+it.previous()); } }
三 集合类各种容器的使用注意细节:
(1)迭代器:
**迭代器的next方法是自动向下取元素,要避免出现NoSuchElementException。
也就是在迭代循环中调用一次next方法一次就要hasNext判断一次,比如语句
sop(it.next()+"..."+it.next())会发生上述异常。
**迭代器的next方法返回值类型是Object,所以要记得类型转换,应用泛型后就不用强转
(2)List集合:
**List集合里面的元素因为是带角标,所以List集合里面的元素都是有序的,
另外List集合可以包含重复元素,也可以包含null。
**List集合有迭代器Iterator,还有一个特有迭代器列表ListIterator
**List集合中判断元素是否相同都是用equals方法,无论contains、remove都依赖equals方法
如往ArrayList集合里面存放学生,同名同年龄视为同一个人,此时就需在学生类复写Object类
里面的equals方法(非常重要!!!要注意!!)
(3)Set集合:
**Set接口里面存放的是元素是无序的,不可以有重复元素,可以包含null
**Set集合只有一种取出方式,就是迭代器Iterator(list集合有get和Iterator)
**Set集合功能和Collection是一致的,没有特殊方法
|--->HashSet:
**集合里面存放的元素是无序的,唯一的
**底层数据结构是哈希表,哈希表结构的数据都是无序的,哈希表结构的操作效率都高效
**线程不同步
**保证元素唯一性的原理是:通过复写hashCode和equals方法
****如果两元素的hashCode值相同,则继续判断两元素equals是否为真
****如果两元素的hashCode值不同,则不会调用equals方法。
**当我们往HashSet集合存放自定义的元素时(比如学生对象),通常都要复写hashCode和equals方法,而且hashCode和equals方法不通过我们调用,HashSet集合底层内部自己调用,自己拿元素去比较
|--->TreeSet
**TreeSet集合可以对存放的元素进行排序,弥补了Set集合元素无序的缺点,且元素是唯一的
**底层数据结构是二叉树,二叉树结构都是有序的
**线程不同步
**TreeSet集合要求往集合里存放的元素自身具备比较性,否则会报错
**TreeSet集合保证元素唯一性的依据是:通过compareTo或者compare方法中的来保证元素的唯一性。
TreeSet排序的第一种方式:让元素自身具备比较性,
定义元素类实现Compareble接口,覆盖compare方法,
此方式是元素的自然顺序。
TreeSet排序的第二种方式:让集合具备比较性
当元素自身不具备比较性或者具备的比较性不是
我们所需要的比较性时,此时就需要让集合具备自定义的比较性。
那如何让集合自身具备比较性呢?
可在集合初始化时,就让集合具备比较方式。
即定义一个类,实现Comparator接口,覆盖compare方法。
注:
**判断元素唯一时,当主要条件一样时,判断次要条件
**两种排序方式都在时,以比较器为主!!!
(4)Map集合:
|--Hashtable
底层是哈希表结构
线程安全的,并且键和值不能为null。
|--HashMap
底层是哈希表结构
线程不安全的,键和值可以为null。
|--LinkedHashMap
底层是链表和哈希表
线程不安全
|--TreeMap
底层是二叉树
线程不安全的