黑马程序员----JAVA基础----集合

------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------

一、集合的由来

1,对象用于封装特有数据,对象用什么存呢?当对象数量较多,而且个数不确时,就可以用集合来存储。也就是说集合的产生是为了存储对象。

数组也可以用来存储对象,为什么不用数组呢?

因为数组的长度是固定的,当对象个数不确定时,就无法用数组来存储。

2,集合与数组的区别:

a,数组可以存储基本数据类型,也可以存储对象,而集合只能用来存储对象,不可以存储基本数据类型。

b,集合的长度是可变的,而数组的长度是固定的。

二、集合框架

1,每一个集合存储对象的方式不尽相同,根据某些特定需求而定的。集合因为内部的数据结构不同,就会产生多种不同的具体容器,这些容器不断向上抽取就形成了集合框架。框架的顶层接口是Collection。

Collection

|----List:有序,存入和取出的顺序一致,元素都具有索引和角标,元素可以重复

|----Vector:内部是数组数据结构,同步的,查询和增删都慢。

|----ArrayList:内部是数组数据结构,非同步的,替代了Vector,查询快,增删慢。

|----LinkedList:内部是链表数据结构,非同步的。查询慢,增删快。

|----Set:无序,存入和取出的顺序通常不一致,元素不可以重复

|----HashSet:内部数据结构是哈希表,不同步。(元素唯一性:依靠hashCode()和equals()方法,来保证元素的唯一性)

|----LinkedHashSet:保证元素的唯一性,同时还是有序的

|----TreeSet:内部结构为二叉树,可以对集合中的元素进行排序,不同步。(元素唯一性:根据比较方法的返回结果是否是0,是0,就是相同元素,不存)

2,Collection的常见方法有:

a,添加:boolean add(Object obj)、boolean addAll(Collection coll)

b,删除:boolean remove(Object obj)、 boolean removeAll(Collection coll)、void clear()(表示清空结合)

c,判断:boolean contains(Object obj)、 boolean containsAll(Collection coll)、boolean isEmpty()

d,获取:int size()、 Iterator iterator()  (该方法用来取出集合中的元素,不同的容器具有不同的迭代器)

e,其他:boolean retainAll()

3,Collection常见方法的代码演示

import java.util.ArrayList;
import java.util.Collection;

public class CollectionDemo {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Collection coll = new ArrayList();
		Collection coll1 = new ArrayList();
		Collection coll2 = new ArrayList();
		show(coll);
		show(coll1,coll2);
	}

	private static void show(Collection coll1, Collection coll2) {
		coll1.add("abc");
		coll1.add("cba");
		coll1.add("nba");
		coll2.add("abc");
		coll2.add("cbc");
		coll2.add("nbc");
		//添加  addAll  将集合coll2中的元素全部添加到coll1中
		coll1.addAll(coll2);
		System.out.println(coll1);
		//删除 removeAll 将coll1中与coll2中相同的元素全部删除
		coll1.removeAll(coll2);
		System.out.println(coll1);
		//判断  containsAll   coll1是否包含coll2中的全部元素,包括返回true,否则返回false
		System.out.println(coll1.containsAll(coll2));
		// 其他  retainsAll 取coll1与coll2的交集,没有交集返回空
		coll1.retainAll(coll2);
		System.out.println(coll1);
	}

	private static void show(Collection coll) {
		// 添加
		coll.add("abc");
		coll.add("cba");
		coll.add("nba");
		// 删除	删除成功返回true,失败返回false
		System.out.println(coll.remove("abc"));
		System.out.println(coll.remove("java"));
		// 判断	包含某元素返回true,不包含则返回false
		System.out.println(coll.contains("cba"));
		System.out.println(coll.contains("java"));
		System.out.println(coll.isEmpty());	// 集合为空返回true,否则返回false
		// 获取  size() 返回集合中元素的个数
		System.out.println(coll.size());
	}

}
对于迭代器来说,由于集合容器的数据结构的不同,其取出数据的方法也就会不同,所以迭代器对象必须依赖于具体的容器,在容器内部实现迭代器的对象,对于使 用者而言,具体的实现过程并不重要,只需要知道如何获取到迭代器对象即可。获取迭代器对象通过itearator()方法。
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class CollectionDemo1 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Collection coll = new ArrayList();
		coll.add("abc");
		coll.add("cba");
		coll.add("nba");
		// 创建迭代器对象  方法一:如果迭代器在取完集合中的元素后还要使用,则使用该方法
		Iterator it1 = coll.iterator();
		while(it1.hasNext()){
			System.out.println(it1.next());
		}
		// 创建迭代器对象 方法二:该方法节省内存,当集合中的数据全部取出后,迭代器对象就释放了,开发时一般用该方法
		for(Iterator it2 = coll.iterator(); it2.hasNext();){
			System.out.println(it2.next());
		}
	}

}

4,List:特有的常见方法(共性特点是可以操作角标)

a,添加 void add(index,element)、 void add(index,Collection)

b,删除 Object remove(index)//删除指定角标的元素,并返回删除的元素

c,修改 Object set(index,element)// 将某角标的元素替换成指定的元素,返回被替换的元素

d,获取 Object get(index)// 得到指定角标的元素  int indexOf(Object)  // 得到指定元素的角标,没有则返回-1

int lastIndexOf(Object) // 从尾部反向得到指定元素的角标,没有则返回-1   

List subList(fromIndex,toIndex)  //获得集合中的部分元素,包含开头,不包含结尾

在List集合中,同样可以使用迭代器获取集合内部的元素,此外,List可以用size()和get(index)方法获取集合内部的元素,这是List集合所特有的方法。

在使用迭代器对象获取集合内部的元素时,不可以对集合内的元素进行修改,否则会引发ConcurrentModificationException 。

为了解决此问题,List集合的ListIterator,这样可以在获取元素的同时,可以对元素进行修改。

另外ListIterator可以反向获取集合中的元素(使用hasprevious() 和previous()方法)

演示代码如下:

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

public class ListDemo {

	public static void main(String[] args) {
		List list = new ArrayList();
		show(list);
		for(Iterator it = list.iterator(); it.hasNext();){
			String str = (String) it.next();
			//在使用迭代器对象获取集合内部的元素时,不可以对集合内的元素进行修改,
			//否则会引发ConcurrentModificationException 
//			if(str.equals("abc2")){
//				it.set("abc9");
//			}
		}
		// List集合特有的取出元素的方法
		for(int i=0; i<list.size(); i++){
			System.out.println("get:"+list.get(i));
		}
		// 使用ListIterator迭代器,可以在获取的同事,对元素进行修改
		ListIterator it1 = list.listIterator();
		while(it1.hasNext()){
			String str = (String)it1.next();
			if(str.equals("abc2")){
				it1.set("ABC2");
			}
		}
		// 可以使用ListIterator进行反向获取元素
		while(it1.hasPrevious()){
			System.out.println("previous:"+it1.previous());
		}
		// 
	}

	
	private static void show(List list) {
		list.add("abc1");
		list.add("abc2");
		list.add("abc3");
		System.out.println(list);
		// 添加
		list.add(1,"ABC");
		System.out.println(list);
		// 删除	返回被删除的元素,index 超出角标界限,就会引发IndexOutOfBoundsException
		System.out.println(list.remove(1));	
		System.out.println(list);
		// 修改	返回被修改的元素,index 超出角标界限,就会引发IndexOutOfBoundsException
		System.out.println(list.set(0,"ABC1"));
		System.out.println(list);
		// 获取	获得指定角标的元素.index 超出角标界限,就会引发IndexOutOfBoundsException
		System.out.println(list.get(0));
		System.out.println(list.indexOf("abc2"));
		System.out.println(list.subList(0, 2));	// 包含头,不包含尾
	}	

}

6,List接口下有Vector、ArrayList和LinkedList三个类

对于Vector(jdk1.0)有自己的一些特有方法  addElements  removeElement removeAllElements等

import java.util.Enumeration;
import java.util.Iterator;
import java.util.Vector;

public class VectorDemo {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Vector v = new Vector();
		// 添加 
		v.addElement("abc1");
		v.addElement("abc2");
		v.addElement("abc3");
		// 特有迭代方法
		for(Enumeration e = v.elements(); e.hasMoreElements();){
			System.out.println("nextElement:"+e.nextElement());
		}
		// Vector也可以用Iterator来取集合中的元素
		for(Iterator it = v.iterator(); it.hasNext();){
			System.out.println(it.next());
		}
	}

}

5,对于LInkedList类,该类的一些特有方法如下:

a,添加:getFirst()getLast()

jdk1.6   offerFirst()offerLast()

b,删除:removeFirst()removeLast()      //获取并移除,如果链表为空,则抛出NotSuchElementException

jdk1.6  pollFirst()pollLast()      //获取并移除,如果链表为空,返回null

c,获得:getFirst()getLast()      //获取但不移除,如果链表为空,则抛出NotSuchElementException

jdk1.6  peekFirst()peekLast()      //获取但不移除,如果链表为空,返回null

根据LinkedList的特有方法,可以模拟一个堆栈(先进后出FILO)或者队列(先进先出FIFO)的数据结构,代码如下:

import java.util.LinkedList;

public class LinkedListDemo {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		DuiLie dl = new DuiLie();
		dl.myAdd("abc1");
		dl.myAdd("abc2");
		dl.myAdd("abc3");
		dl.myAdd("abc4");
		// 循环得到集合中的元素
		while(!dl.isNull()){
			String str = (String) dl.myGet();
			System.out.println(str);
		}
	}

}
class DuiLie{
	//创建LinkedList对象并私有化
	private LinkedList list;

	public DuiLie() {
		list = new LinkedList();
	}
	// 定义添加方法
	public void myAdd(Object obj){
		list.addFirst(obj);
	}
	// 定义获取方法
	public Object myGet(){
		return list.removeLast();
//		return list.removeFirst();    使用该条语句则为堆栈结构
	}
	// 定义方法判断集合是否为空
	public boolean isNull(){
		return list.isEmpty();
	}
}

6,对于ArrayList集合,向其中添加自定义对象(Person),如下所示:

import java.util.ArrayList;
import java.util.Iterator;

public class ArrayListDemo {

	public static void main(String[] args) {
		// 创建集合
		ArrayList al = new ArrayList();
		// 向集合中添加自定义对象
		al.add(new Person("lisi1",21));
		al.add(new Person("lisi2",22));
		al.add(new Person("lisi3",23));
		al.add(new Person("lisi4",24));
		// 使用迭代器依次取出集合中的元素
		for(Iterator it = al.iterator(); it.hasNext();){
			// 将集合中的元素赋值给具体对象时,一般需要进行强制转换,因为集合中的元素的类型为Object类
			Person p = (Person) it.next();
			System.out.println(p.getName()+"----"+p.getAge());
		}
		// 基本数据类型赋值给引用数据类型时会自动装箱
		// 当引用数据类型和基本数据类型做运算时,自动拆箱
		al.add(5);
	}

}

class Person{
	/*
	 * 自定义对象,有两个成员变量name和age,
	 * 使用alt+shift+s组合可快速创建set和get方法,以及构造函数
	 */
	private String name;
	private int age;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public Person() {
		super();
	}
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	
}

7,Set类集合下面有两个常用的子类HashSet和TreeSet。

对于HashSet,其内部数据结构为哈希表,非同步的,根据哈希表判断集合内的元素是否相同。

哈希表判断元素是否相同根据两个方面:哈希值和内容

a,先判断两个元素的哈希值是否相同,如果相同则判断二者的内容是否相同。如果不同,则无需进一步判断。

b,判断哈希值是否相同,用的是hashCode方法;判断内容是否相同,用的是equals()方法。

注意:如果哈希值不同,无需判断内容!!!

下面分别在HashSet中存储字符串对象和自定义对象:

import java.util.HashSet;
import java.util.Iterator;

public class HashSetDemo {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		HashSet hs = new HashSet();
		// 向HashSet中存储字符串对象
		show1(hs);
		// 清空结合,存储自定义对象
		hs.clear();
		show2(hs);
	}

	private static void show2(HashSet hs) {
		hs.	add(new Person("lisi4",24));
		hs.	add(new Person("lisi7",27));
		hs.	add(new Person("lisi1",21));
		hs.	add(new Person("lisi9",29));
		// 如果自定义对象内没有重写hashCode方法和equals()方法,那么下面语句将会被存储到集合中
		// 字符串对象中已经覆盖了hashCode()和equals()方法,因此,当元素相同时,无法存进集合中
		hs.	add(new Person("lisi7",27));
		for(Iterator it = hs.iterator();it.hasNext();){
			Person p = (Person) it.next();
			System.out.println(p.getName()+"---"+p.getAge());
		}
	}

	private static void show1(HashSet hs) {
		hs.add("haha");
		hs.add("hehe");
		hs.add("xixi");
		// 下面一句无法存储,因为Set类集合保证了集合内的元素的唯一性
		hs.add("haha");
		for(Iterator it = hs.iterator();it.hasNext();){
			// 输出结果一般无序,所谓无序指存入和取出顺序不一致
			System.out.println(it.next());
		}
	}

}
class Person{
	/*
	 * 自定义对象,有两个成员变量name和age,
	 * 使用alt+shift+s组合可快速创建set和get方法,以及构造函数
	 */
	private String name;
	private int age;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public Person() {
		super();
	}
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	/*
	 * 覆盖hashCode和equals方法,为了使Person类存储到Set类集合时,可以进行比较判断
	 */
	@Override
	public int hashCode() {
		// 为了确保哈希值的不同,通常会乘上一个数
		return name.hashCode()+age*39;
	}
	@Override
	public boolean equals(Object obj) {
		// 健壮性判断
		if(this==obj)
			return true;
		if(!(obj instanceof Person))
			throw new ClassCastException("类型错误!");
		Person p = (Person) obj;
		return this.name.equals(p.name)&&this.age==p.age;
	}
}

8,练习:去除ArrayList中的重复元素

a,在ArrayList中,分别通过字符串对象(覆盖了equals()方法)和自定义对象来验证contains()方法依据equals()方法来判断集合内的元素是否相同。

b,在ArrayList中,验证了remove()方法依据equals()方法来判断集合内的元素是否相同。

c,总结:在List类中判断两个元素是否相同,用的是equals()方法,而在HashSet中,判断两个元素是否相同,依靠的是hashCode()和equals()方法。

import java.util.ArrayList;
import java.util.Iterator;

public class ArrayList2 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		ArrayList al = new ArrayList();
		// 通过字符串对象和自定义对象验证contains()方法用equals()方法来判断集合内的元素是否相同
		show1(al);
		al.clear();
		show2(al);
		al.clear();
		// 验证remove()方法依据equals()方法来判断集合内的元素是否相同
		show3(al);
	}

	private static void show3(ArrayList al) {
		// 添加自定义对象Person类
		al.add(new Person("lisi1",21));
		al.add(new Person("lisi2",22));
		al.add(new Person("lisi3",23));
		al.add(new Person("lisi4",24));
		print(al);
		// remove方法依靠的也是equals()方法,移除成功返回true,失败返回false
		al.remove(new Person("lisi4",24));
		print(al);
	}

	private static void show2(ArrayList al) {
		al.add(new Person("lisi1",21));
		al.add(new Person("lisi2",22));
		al.add(new Person("lisi3",23));
		al.add(new Person("lisi4",24));
		// 如果Person类中没有覆盖equals()方法,那么下面两个对象经过getSingleElement2()
		// 仍会存在。即contains方法依靠的是equals()方法
		al.add(new Person("lisi3",23));
		al.add(new Person("lisi4",24));
		al = getSingleElement2(al);
		print(al);
	}

	/**
	 * @param al
	 */
	private static void print(ArrayList al) {
		for(Iterator it = al.iterator(); it.hasNext();){
			// 将集合中的元素赋值给具体对象时,一般需要进行强制转换,因为集合中的元素的类型为Object类
			Person p = (Person) it.next();
			System.out.println(p.getName()+"----"+p.getAge());
		}
	}

	private static ArrayList getSingleElement2(ArrayList al) {
		// TODO Auto-generated method stub
		// 定义一个临时容器
		ArrayList temp = new ArrayList();
		// 迭代al集合
		for(Iterator it = al.iterator(); it.hasNext();){
			Object obj = it.next();
			// 如果临时容器中没有obj,就将其存储到temp集合中
			// 对于自定义对象来讲,如果没有复写equals()方法,对于Person类来所,即使年龄和姓名相同,也认为二者是不同的
			if(!temp.contains(obj))
				temp.add(obj);
		}
		return temp;
	}

	private static void show1(ArrayList al) {
		// 添加字符串对象到集合中,List类集合中的元素可以重复,
		al.add("abc1");
		al.add("abc2");
		al.add("abc2");
		al.add("abc1");
		al.add("abc");
		System.out.println(al);
		// 创建方法,移除集合中的重复元素
		al = getSingleElement(al);
		System.out.println(al);
	}

	private static ArrayList getSingleElement(ArrayList al) {
		// 定义一个临时容器
		ArrayList temp = new ArrayList();
		// 迭代al集合
		for(Iterator it = al.iterator(); it.hasNext();){
			Object obj = it.next();
			// 如果临时容器中没有obj,就将其存储到temp集合中
			// 如何判断两个元素是否相同?其实contains()方法依靠的是equals()方法来进行判断
			if(!temp.contains(obj))
				temp.add(obj);
		}
		return temp;
	}

}
class Person{
	/*
	 * 自定义对象,有两个成员变量name和age,
	 * 使用alt+shift+s组合可快速创建set和get方法,以及构造函数
	 */
	private String name;
	private int age;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public Person() {
		super();
	}
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	/*
	 * 覆盖hashCode和equals方法,为了使Person类存储到Set类集合时,可以进行比较判断
	 */
	@Override
	public int hashCode() {
		// 为了确保哈希值的不同,通常会乘上一个数
		return name.hashCode()+age*39;
	}
	@Override
	public boolean equals(Object obj) {
		// 健壮性判断
		if(this==obj)
			return true;
		if(!(obj instanceof Person))
			throw new ClassCastException("类型错误!");
		Person p = (Person) obj;
		return this.name.equals(p.name)&&this.age==p.age;
	}
	
}

9,TreeSet: 内部结构为二叉树,可以对集合中的元素进行排序,不同步。(元素唯一性:根据比较方法的返回结果是否是0,是0,就是相同元素,不存)

对于自定义对象,如过要存到二叉树中,那么自定义对象需要覆盖Coparable接口或自定义一个比较器。与hashCode()和equals()方法无关。

如果不按照对象中具有的自然顺序进行排序或者对象不具有自然排序怎么办?

这时可以使用TreeSet集合的第二种排序方式:让集合具有排序功能,即在TreeSet的构造函数中传递一个比较器Comparator接口的子类对象。

对于TreeSet类,如果想让取出元素的顺序与存入的顺序一致(相反),可以将compare()方法返回1(-1)


import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;

public class TreeSetDemo {

	
	public static void main(String[] args){
		TreeSet ts = new TreeSet();
		// 向ts中添加字符串对象
		show1(ts);
		ts.clear();
		// 向ts中添加自定义对象,让自定义对象具有比较功能
		show2(ts);
		ts.clear();
		// 第二种排序方式,将Comparator接口的子类对象作为TreeSet构造函数的参数
		// 让TreeSet集合具有比较功能
		show3();
	}

	private static void show3() {
		TreeSet ts = new TreeSet(new ComparatorByName());
		ts.add(new Person("lisi",21));
		ts.add(new Person("zhangsan",22));
		ts.add(new Person("wangwu",23));
		ts.add(new Person("sunliu",24));
		print(ts);
	}

	
	private static void show2(TreeSet ts) {
		// 对于自定义对象来讲,如果实现Comparable接口,那么TreeSet就无法对其进行排序,会抛出ClassCastException异常
		// 如果要对自定义对象进行排序,就需要实现Comparable接口。
		ts.add(new Person("lisi1",21));
		ts.add(new Person("lisi2",22));
		ts.add(new Person("lisi3",23));
		ts.add(new Person("lisi4",24));
		print(ts);
	}

	private static void show1(TreeSet ts) {
		// 添加字符串对象
		ts.add("abc");
		ts.add("cde");
		ts.add("ddw");
		ts.add("abc");	// 由于Set类集合保证元素的唯一性,该对象无法存储
		System.out.println(ts);
	}
	
	private static void print(TreeSet ts) {
		for(Iterator it = ts.iterator(); it.hasNext();){
			// 将集合中的元素赋值给具体对象时,一般需要进行强制转换,因为集合中的元素的类型为Object类
			Person p = (Person) it.next();
			System.out.println(p.getName()+"----"+p.getAge());
		}
	}

}

class ComparatorByName implements Comparator{

	@Override
	public int compare(Object o1, Object o2) {
		// TODO Auto-generated method stub
		Person p1 = (Person) o1;
		Person p2 = (Person) o2;
		int temp = p1.getName().compareTo(p2.getName());
		return temp==0?p1.getAge()-p2.getAge():temp;
	}
	
}

class Person implements Comparable{
	/*
	 * 自定义对象,有两个成员变量name和age,
	 * 使用alt+shift+s组合可快速创建set和get方法,以及构造函数
	 */
	private String name;
	private int age;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public Person() {
		super();
	}
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	@Override
	public int compareTo(Object o) {
		// TODO Auto-generated method stub
		Person p = (Person) o;
		// 依据姓名对元素进行排序
		// 如果进行反向排序,可以将this和p调换位置
//		int temp = this.name.compareTo(p.name);
		int	temp = p.name.compareTo(this.name);
		return temp==0?this.age-p.age:temp;
	}
	
}

三、Map集合

1,Map集合存储的都是键值对,并且键是唯一的。

Map集合与Collection集合的区别:

a,Map一次添加一对元素,Collection一次添加一个元素

b,Map也称双列集合,Collection也称单列集合

2,Map常用子类

|----HashTable:内部是哈希表结构,同步的,不允许null作为键和值

|----Properties:用来存储键值对类型的配置文件信息,可以与IO技术相结合。

|----HashMap:内部是哈希表结构,非同步,允许null作为键和值

|----TreeMap:内部是二叉树结构,非同步,可以对Map集合中的键进行排序

3,Map集合常用方法:

a,添加:value put(key,value):返回前一个和key关联的值,如果没有则返回null

b,删除:void clear() 清空Map集合

  value remove(key) :根据指定的键,删除与该键对应的值

c,判断:boolean containsKey(key):是否包含指定的key

  boolean containsValue(value):是否包含指定的value

  boolean isEmpty():集合是否为空

d,获取:value get(key):通过指定的键获取与之对应的值,如果没有则返回null,可以通过返回null,来判断是否包含指定键。

  int size(): 获取键值对的个数

常用方法演示:

import java.util.HashMap;
import java.util.Map;

public class MapDemo {

	public static void main(String[] args) {
		Map m = new HashMap();
		// 添加元素
		System.out.println(m.put(8, "wangcai"));	// 返回null,因为存放8之前,集合中不包含该键值对
		System.out.println(m.put(8, "wangcai"));	// 返回wangcai,返回前一个和key关联的值
		m.put(2, "zhangsan");
		m.put(7, "zhaoliu");
		System.out.println(m);
		// 删除元素
		System.out.println("remove:"+m.remove(2));	// 根据指定的键,删除与该键对应的值
		// 判断
		System.out.println("isEmpty:"+m.isEmpty());
		System.out.println("containsKey:"+m.containsKey(7));
		System.out.println("containsValue:"+m.containsValue("zhaoliu"));
		// 获取		通过指定的键获取与之对应的值,如果没有则返回null
		System.out.println("get:"+m.get(7));
		System.out.println("get:"+m.get(2));	// 返回null
		System.out.println("size:"+m.size());
	}

}

2,获取Map集合中的元素有三种方法:keySet()、entrySet()、values()。如下所示:

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class MapDemo2 {

	public static void main(String[] args) {
		Map map = new HashMap();
		map.put(2, "zhangsan");
		map.put(7, "zhaoliu");
		map.put(8, "wangcai");
		map.put(6,"sunqian");
		/*
		 * 第一种迭代方法
		 * 取出Map中所有的元素
		 * 原理:通过keySet()方法获取Map中所有的键所在的Set集合,再通过Set的迭代器获取到每一个键
		 * 再根据键获取相应的值即可
		 */
		for(Iterator it = map.keySet().iterator(); it.hasNext();){
			Integer key = (Integer) it.next();
			String value = (String) map.get(key);
			System.out.println(key+"---"+value);
		}
		/*
		 * 第二种迭代方法
		 * entrySet方法
		 * 该方法将键和值的映射关系作为对象存储到Set集合中,而这个映射关系的类型就是Map。Entry类型
		 */
		for(Iterator<Map.Entry<Integer, String>> it = map.entrySet().iterator(); it.hasNext();){
			Map.Entry<Integer, String> me = it.next();
			Integer key = me.getKey();
			String value = me.getValue();
			System.out.println(key+"---"+value);
		}
		/*
		 * 第三种迭代方法
		 * values()方法
		 */
		for(Iterator<String> it = map.values().iterator(); it.hasNext();){
			System.out.println(it.next());
		}
	}
	
}


3,向HashMap和TreeMap中存储自定义对象

与HashSet和TreeSet相似,存入HashMap的对象要覆盖hashCode()和equals()方法;存入到TreeMap的对象要实现Comparale接口,或者让TreeMap具有

排序功能,即将Comparator接口的子类对象作为TreeMap构造函数的参数。

import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;

public class MapDemo3 {

	public static void main(String[] args){
		// 向HashMap中存储自定义对象Person
		show1();
		System.out.println();
		// 使用TreeMap对自定义对象进行排序
		show2();
	}

	private static void show2() {
		TreeMap<Person,String> tm = new TreeMap<Person,String>();
		// 存储自定义对象,因为TreeMap要对自定义对象进行排序,因此自定义对象需要实现Comparable接口
		// 或者TreeMap集合具有比较功能,即将Comparator接口的子类对象作为TreeMap构造函数的参数
//		 TreeMap<Person,String> tm = new TreeMap<Person,String>(new ComparatorByName());
		tm.put(new Person("lisi",37), "beijing");
		tm.put(new Person("zhaoliu",24), "shanghai");
		tm.put(new Person("xiaoqiang",38), "shenyang");
		tm.put(new Person("wangcai",28), "dalian");
		tm.put(new Person("zhaoliu",24), "tieling");
		print(tm);
	}

	private static void show1() {
		HashMap<Person,String> hm = new HashMap<Person,String>();
		// 向集合中添加自定义对象,因为HashMap的结构是哈希表结构,所以自定义对象应该覆盖hashCode()和equals()方法
		hm.put(new Person("lisi",37), "beijing");
		hm.put(new Person("zhaoliu",24), "shanghai");
		hm.put(new Person("xiaoqiang",38), "shenyang");
		hm.put(new Person("wangcai",28), "dalian");
		hm.put(new Person("zhaoliu",24), "tieling");	// 如果不覆盖hashCode()和equals()方法,该对象将会被存入到集合中
		// 下面两句可以简化为for循环内的一句
//		Set<Map.Entry<Person, String>> entrySet = hm.entrySet();
//		Iterator<Map.Entry<Person, String>> it = entrySet.iterator();
		for(Iterator<Map.Entry<Person,String>> it = hm.entrySet().iterator(); it.hasNext();){
			Entry<Person, String> me = it.next();
			Person p = me.getKey();
			String value = me.getValue();
			System.out.println(value+":"+p.getName()+"---"+p.getAge());
		}
	}

	/**
	 * @param ts
	 */
	private static void print(TreeMap<Person, String> ts) {
		for(Iterator<Map.Entry<Person,String>> it = ts.entrySet().iterator(); it.hasNext();){
			Entry<Person, String> me = it.next();
			Person p = me.getKey();
			String value = me.getValue();
			System.out.println(value+":"+p.getName()+"---"+p.getAge());
		}
	}
}

class ComparatorByName implements Comparator{

	@Override
	public int compare(Object o1, Object o2) {
		// TODO Auto-generated method stub
		Person p1 = (Person) o1;
		Person p2 = (Person) o2;
		int temp = p1.getName().compareTo(p2.getName());
		return temp==0?p1.getAge()-p2.getAge():temp;
//		return 1;	// 存入与取出的顺序一致
	}
	
}

class Person implements Comparable{
	/*
	 * 自定义对象,有两个成员变量name和age,
	 * 使用alt+shift+s组合可快速创建set和get方法,以及构造函数
	 */
	private String name;
	private int age;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public Person() {
		super();
	}
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	/*
	 * 覆盖hashCode和equals方法,为了使Person类存储到Set类集合时,可以进行比较判断
	 */
	@Override
	public int hashCode() {
		// 为了确保哈希值的不同,通常会乘上一个数
		return name.hashCode()+age*39;
	}
	@Override
	public boolean equals(Object obj) {
		// 健壮性判断
		if(this==obj)
			return true;
		if(!(obj instanceof Person))
			throw new ClassCastException("类型错误!");
		Person p = (Person) obj;
		return this.name.equals(p.name)&&this.age==p.age;
	}
	@Override
	public int compareTo(Object o) {
		// TODO Auto-generated method stub
		Person p = (Person) o;
		// 依据姓名对元素进行排序
		// 如果进行反向排序,可以将this和p调换位置
		int temp = this.age-p.age;
//		int	temp = p.name.compareTo(this.name);
		return temp==0?this.name.compareTo(p.name):temp;
	}
	
}

4,利用Map集合的一个小练习

统计字符串中字符的个数,并以a(1) b(2)的方式打印

思路:将字符串转换为字符数组,遍历字符数组,将字符作为键存入到HasnMap集合中,第一次存入时,将其值设为1。如果集合中已存在该字符,则

将该字符对应的值加1。最后通过迭代器遍历集合,并打印结果。

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class MapDemo4 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		String str = "sladkdfjsiialkdfjasdfjqweoirjaa";
		/*
		 * 将字符串转成字符数组
		 * 遍历数组
		 * 将字符作为Map集合的键
		 * 如果存在键,则再原来基础上+1
		 * 如果不存在,存进集合,值为1
		 */
		// 将字符串转换成字符数组
		char[] ch = str.toCharArray();
		// 创建Map集合,用来存储字符
		HashMap<Character,Integer> hm = new HashMap<Character,Integer>();
		// 遍历数组
		for(int i=0; i<ch.length; i++){
			// 如果如果集合中已存在该字符,则将该字符对应的值加1
			if(hm.containsKey(ch[i])){
				Integer count = hm.get(ch[i]);
				hm.put(ch[i],++count);
			}
			else
				hm.put(ch[i],1);	//第一次存入时,将其值设为1
		}
		// 通过迭代,打印结果
		for(Iterator<Map.Entry<Character, Integer>> it = hm.entrySet().iterator(); it.hasNext();){
			Map.Entry<Character, Integer> me = it.next();
			Character key = me.getKey();
			Integer value = me.getValue();
			System.out.print(key+"("+value+")"+" ");
		}
	}

}





版权声明:本文为lyl7885000原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。