Java基础(集合——Map、Collcetions工具类)


Map
一、体系
          Map
            |——Hashtable    底层是哈希表数据结构,不可以存入null键或null值,线程是同步的,效率低,JDK1.0(被HashMap替代)
            |——HashMao     底层是哈希表数据结构,可以存入null键或null值,线程是不同步的  效率比较高,JDK1.1
            |——TreeMap     底层是二叉树数据结构,线程是不同步的,可以用于给Maori集合中的键进行排序
二、Maori和collection的不同
1、Map和Collection在集合框架中属于并列存在
2、Map存储的是键值对
3、Map存储元素使用的是put方法,Collection存储元素使用的是add方法
4、Map中没有直接元素的方法,而是先转成Set集合,在使用迭代取出
5、Map中的键是唯一的
6、其实Set底层使用的就是Map集合
三、Map格式
Map map = new HashMap();
k:代表键的类型,是唯一的,使用put方法添加时,可以添加相同的键,但是后面的键对应的值会覆盖前面键对应的值。
V:  代表值得类型,不是唯一的。
四、Map集合常用方法

1、增加
1、put(K key,V value)    返回值为V  注:使用put添加元素时,如果要添加的元素不存在,则会返回null,如果要添加的元素已经存在,那么新添加的键上的value会覆盖和指定要添加的键相同的value上的值
2、 putAll(Map m)         返回值类型为void   注:用于添加指定集合,添加的集合中的键必须是已有集合键的类型或其子类型,添加的集合中的值必须是又有集合值得类型或其子类型
2、删除
1、 clear()          返回值为void    清空集合

2、remove(Object key)  返回值为V    用于删除指定键,并返还指定键上的值

3、获取
1、 entrySet()    返回值  Set>   注:该返回值是一个set集合 而返回的set集合中元素的类型必须是Map.Entry类型    Map.Entry是一个内部类
2、 get(Object key)  返回值为V   用于返回指定键上的value
3、 keySet()          返回值为  Set     获取集合中的所有键,方便使用迭代器
4、判断
1、 containsKey(Object key)        判断指定的键是否存在
2、 containsValue(Object value)    判断指定的值是否存在
3、 isEmpty()        返回值为 boolean   用于判断集合是否为空
五、Map集合常用的两种取出方式
1、 keySet()
       原理:将Map集合中的所有键取出存入到Set集合中,因为Set集合具备迭代器,所以可以使用keySet取出所有键,然后在使用迭代的方式取出所有的值。
       图例:
              Java基础(集合——Map、Collcetions工具类)_第1张图片
2、 entrySet()
       原理:将Map集合中的映射关系存入到Set集合中,而这个关系的数据类型就是Set>    而,其实Entry它就是一个Map接口中的一个内部接口,而它有俩个方法可以获取元素,getKey()、getValue();
       图例:
               Java基础(集合——Map、Collcetions工具类)_第2张图片
二、entrySet部分源码:
       
class Map
{
	//这里必须是静态的,应为Map.Entry()是直接调用的
	public static interface Entry
	{
		public abstract Object getKay();
		public abstract Object getValue();
	}
}
class HashMap implements Map
{
	//必须要实现Map中的方法和Entry中方法
	class Node implements Entry
	{
		public Object getKey(){}
		public Object getValue();
	}
}
三、keySet、entrySet练习
       
/*获取Map中的元素
keySet(0
entrySet()*/
import java.util.*;

class  MapDemo
{
	public static void main(String[] args) 
	{
		Map map = new HashMap();

		map.put("02","zhangsan2");
		map.put("03","zhangsan3");
		map.put("01","zhangsan1");
		map.put("04","zhangsan4");
		/*----------ketSet---------*/
		Set set = map.keySet();
		for(Iterator it = set.iterator();it.hasNext();){
			String key = it.next();      //获取键
			String value = map.get(key);   //获取值
			System.out.println(key+"=="+value);
		}

		/*---------entrySet----------*/
		Set> se = map.entrySet();     //这里返回的是映射关系,所以泛型应该是Map.Entry
		for(Iterator > it = se.iterator();it.hasNext();){
			Map.Entry me = it.next();
			String key = me.getKey();     //获取键
			String value = me.getValue();   //获取值
			System.out.println(key+"==================="+value);
		}
	}
}
四、去除重复对象
       
/*
每一个学生都有对应的归属地。
学生Student,地址String。
学生属性:姓名,年龄。
注意:姓名和年龄相同的视为同一个学生。
保证学生的唯一性。



1,描述学生。

2,定义map容器。将学生作为键,地址作为值。存入。

3,获取map集合中的元素。

*/
//定义学生类
import java.util.*;
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;}
	//因为不确定用户使用的是TreeMap还是HashMap 所以应该复写equals方法、hasCode方法和compareTo方法
	public boolean equals(Object obj){
		if(!(obj instanceof Student))
			throw new ClassCastException("类型不匹配");
		return this.name.equals(((Student)obj).name)&&this.age==age;
	}
	public int hashCode(){
		return this.name.hashCode()+age*21;
	}
	public int compareTo(Student s){
		int num = this.name.compareTo(s.name);
		if(num==0)
			return new Integer(this.age).compareTo(new Integer(s.age));
		return num;
	}
}

class  MapDemo1
{
	public static void main(String[] args) 
	{
	//	HashMap hm = new HashMap();
		TreeMap hm = new TreeMap();
		hm.put(new Student("lisi1",21),"beijing");
		hm.put(new Student("lisi1",21),"tianjin");
		hm.put(new Student("lisi2",22),"shanghai");
		hm.put(new Student("lisi3",23),"nanjing");
		hm.put(new Student("lisi4",24),"wuhan");
		/*------keySet-----*/
		for(Iterator it = hm.keySet().iterator();it.hasNext();){
			Student stu = it.next();
			String value = hm.get(stu);
			System.out.println(stu.getName()+":"+stu.getAge()+"=="+value);
		}
		/*--------entrySet--------*/
		for(Iterator> it = hm.entrySet().iterator();it.hasNext();){
			Map.Entry me = it.next();
			Student stu = me.getKey();
			System.out.println(stu.getName()+":"+stu.getAge()+"========"+me.getValue());
		}
	}
}
五、自定义比较器
       
//定义学生类
import java.util.*;
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;}
	//因为不确定用户使用的是TreeMap还是HashMap 所以应该复写equals方法、hasCode方法和compareTo方法
	public boolean equals(Object obj){
		if(!(obj instanceof Student))
			throw new ClassCastException("类型不匹配");
		return this.name.equals(((Student)obj).name)&&this.age==age;
	}
	public int hashCode(){
		return this.name.hashCode()+age*21;
	}
	public int compareTo(Student s){
		int num = this.name.compareTo(s.name);
		if(num==0)
			return new Integer(this.age).compareTo(new Integer(s.age));
		return num;
	}
}
//自定义比较器
//需求:对学生对象的年龄进行降序排序。
class stuAgeComparator implements Comparator
{
	public int compare(Student stu1,Student stu2){
		int num = new Integer(stu2.getAge()).compareTo(new Integer(stu1.getAge()));
		if(num==0)
			return stu2.getName().compareTo(stu1.getName());
		return num;
	}
}
class  MapDemo1
{
	public static void main(String[] args) 
	{
	//	HashMap hm = new HashMap();
		TreeMap hm = new TreeMap(new stuAgeComparator());
		hm.put(new Student("lisi1",21),"beijing");
		hm.put(new Student("lisi1",21),"tianjin");
		hm.put(new Student("lisi2",22),"shanghai");
		hm.put(new Student("lisi3",23),"nanjing");
		hm.put(new Student("lisi4",24),"wuhan");
		/*------keySet-----*/
		for(Iterator it = hm.keySet().iterator();it.hasNext();){
			Student stu = it.next();
			String value = hm.get(stu);
			System.out.println(stu.getName()+":"+stu.getAge()+"=="+value);
		}
		/*--------entrySet--------*/
		for(Iterator> it = hm.entrySet().iterator();it.hasNext();){
			Map.Entry me = it.next();
			Student stu = me.getKey();
			System.out.println(stu.getName()+":"+stu.getAge()+"========"+me.getValue());
		}
	}
}
六、获取字母出现的次数
       
/*
练习:
"sdfgzxcvasdfxcvdf"获取该字符串中的字母出现的次数。

希望打印结果:a(1)c(2).....

通过结果发现,每一个字母都有对应的次数。
说明字母和次数之间都有映射关系。

注意了,当发现有映射关系时,可以选择map集合。
因为map集合中存放就是映射关系。


什么使用map集合呢?
当数据之间存在这映射关系时,就要先想map集合。

思路:
1,将字符串转换成字符数组。因为要对每一个字母进行操作。

2,定义一个map集合,因为打印结果的字母有顺序,所以使用treemap集合。

3,遍历字符数组。
	将每一个字母作为键去查map集合。
	如果返回null,将该字母和1存入到map集合中。
	如果返回不是null,说明该字母在map集合已经存在并有对应次数。
	那么就获取该次数并进行自增。,然后将该字母和自增后的次数存入到map集合中。覆盖调用原理键所对应的值。

4,将map集合中的数据变成指定的字符串形式返回。
*/


import java.util.*;
class  MapDemo2
{
	public static void main(String[] args) 
	{
		String str = getCount("abcdabcdeabffgac");  
		System.out.println(str.substring(0,str.length()-1));
	}
	public static String getCount(String str){
		//将字符串转换成字符数组
		char [] ch = str.toCharArray();
		//定义集合存储每个字符以及出现的次数
		Map ma = new TreeMap ();
		String strs = "";
		for(int i = 0;i> it = ma.entrySet().iterator();it.hasNext();){
			Map.Entry me = it.next();
			strs+= me.getKey()+"("+me.getValue()+"),";
		}
		return strs;
	}
}
七、Map集合扩展
      
/*
需求:有一个学校,这个学校有两个班级,每个班级有两名学生,
用代码实现打印每个班级吗名称及学生
map扩展知识。

map集合被使用是因为具备映射关系。

"yureban"   Student("01" "zhangsan");

"yureban" Student("02" "lisi");

"jiuyeban" "01" "wangwu";
"jiuyeban" "02" "zhaoliu";

一个学校有多个教室。每一个教室都有名称。
*/


//定义学生类
import java.util.*;
class Student implements Comparable
{
	private String name;
	private String sex;
	public Student(String name,String sex){
		this.name = name;
		this.sex = sex;
	}
	public String getName()	{return name;}
	public String getSex()	{return sex;}
	public boolean equals(Object obj){
		if(!(obj instanceof Student))
			throw new ClassCastException("类型不匹配");
		return this.name.equals(((Student)obj).name)&&this.sex.equals(((Student)obj).sex); 
		}
	public int hashCode()	{return this.name.hashCode()+sex.hashCode()*21;}
	public int compareTo(Student stu){
		int num = this.name.compareTo(stu.name);
		if(num == 0)
			return new Integer(this.sex).compareTo(new Integer(stu.sex));
		return num;
	}
}
class  MapDemo4
{
	public static void main(String[] args) 
	{
		/*----第一种------*/
		/*
		//创建学校集合
		Map> czbk = new TreeMap>();
		//创建基础班集合
		Map caseStudent = new TreeMap();
		//创建高级班集合
		Map advStudent = new TreeMap();
		//把班级添加到学校所在的集合
		czbk.put("case",caseStudent);
		czbk.put("adv",advStudent);
		//基础班添加学生信息
		caseStudent.put("c01",new Student("ZhangSan","man"));
		caseStudent.put("c02",new Student("Lisi","woman"));
		//高级班添加学生信息
		advStudent.put("a01",new Student("WangWu","man"));
		advStudent.put("a02",new Student("ZhaoLiu","Woman"));
		//使用迭代遍历学校
		for(Iterator>> it = czbk.entrySet().iterator();it.hasNext();){
			Map.Entry> me = it.next();
			//打印班级名
			System.out.println(me.getKey());
			//获取班级信息
			Map ma = me.getValue();
			//遍历班级信息
			for(Iterator> iter = ma.entrySet().iterator();iter.hasNext();){
				Map.Entry mes = iter.next();
				//获取学生信息
				Student stu = mes.getValue();
				//打印学生信息
				System.out.println(mes.getKey()+"=="+stu.getName()+":"+stu.getSex());
			}
		}
		*/
		/*------第二种-比较常用-----*/
		//创建学校集合
		Map> czbk = new TreeMap>();
		//创建基础班集合
		List caseStudent = new ArrayList();
		//创建高级班集合
		List advStudent = new ArrayList();
		//把班级添加到学校所在的集合
		czbk.put("case",caseStudent);
		czbk.put("adv",advStudent);
		//基础班添加学生信息
		caseStudent.add(new Student("ZhangSan","man"));
		caseStudent.add(new Student("Lisi","woman"));
		//高级班添加学生信息
		advStudent.add(new Student("WangWu","man"));
		advStudent.add(new Student("ZhaoLiu","Woman"));
		getShow(czbk);
	}
	public static void getShow(Map> ma){
		for(Iterator it = ma.keySet().iterator();it.hasNext();){
			String key = it.next();
			System.out.println(key);
			List stu = ma.get(key);
			for(Iterator iter = stu.iterator();iter.hasNext();){
				Student st =iter.next();
				System.out.println(st.getName()+":"+st.getSex());
			}
		}
	}
}
Collections工具类

一、概述

        Collections是对集合框架的一个工具类。它里边的方法都是静态的,不需要创建对象。并未封装特有数据。

       Collections工具类中大部分方法是用于对List集合进行操作的,如比较,二分查找,随机排序等

二、Collection和Collections的区别

Collection是集合框架中的一个顶层接口,它里面定义了单列集合的共性方法。
        它有两个常用的子接口,
        List:对元素都有定义索引。有序的。可以重复元素。
        Set:不可以重复元素。无序。

Collections是集合框架中的一个工具类。该类中的方法都是静态的
        提供的方法中有可以对list集合进行排序,二分查找等方法。
        通常常用的集合都是线程不安全的。因为要提高效率。
        如果多线程操作这些集合时,可以通过该工具类中的同步方法,将线程不安全的集合,转换成安全的。

三、常用方法

1、增加

1、addAll(Collection c, T... elements)     将所有指定元素添加到指定 collection 中。

2、获取

1、binarySearch(List> list, T key) 

       返回要查询的指定元素在list集合中的位置,如果没有返回插入点
2、binarySearch(List list, T key, Comparator c)

       指定一个比较器,返回要查询的指定元素在排序后List集合中的位置,如果没有,返回插入点

3、frequency(Collection c,Object o)
          返回指定 collection 中等于指定对象的元素数。

4、indexOfSubList(List source,List target)
          返回指定源列表中第一次出现指定目标列表的起始位置;如果没有出现这样的列表,则返回 -1。

5、lastIndexOfSubList(List source,List target)
          返回指定源列表中最后一次出现指定目标列表的起始位置;如果没有出现这样的列表,则返回 -1。

6、shuffle(List list)
          使用默认随机源对指定列表进行置换。

3、Copy

1、copy(List dest,List src)
          将所有元素从一个列表复制到另一个列表。

4、判断

1、disjoint(Collection c1,Collection c2)
          如果两个指定 collection 中没有相同的元素,则返回 true

5、替换

1、fill(List list, T obj)
          使用指定元素替换指定列表中的所有元素。

2、replaceAll(List list, T oldVal, T newVal)
          使用另一个值替换列表中出现的所有某一指定值。

6、反转

1、reverse(List list)
          反转指定列表中元素的顺序。

7、获取最值

1、max(Collection coll)
          根据元素的自然顺序,返回给定 collection 的最大元素。

2、max(Collection coll, Comparator comp)
          根据指定比较器产生的顺序,返回给定 collection 的最大元素。

3、min(Collection coll)
          根据元素的自然顺序 返回给定 collection 的最小元素。

4、 min(Collection coll, Comparator comp)
          根据指定比较器产生的顺序,返回给定 collection 的最小元素。

8、比较器

1、reverseOrder()
          返回一个比较器,它强行逆转实现了 Comparable 接口的对象 collection 的自然顺序

2、reverseOrder(Comparator cmp)
          返回一个比较器,它强行逆转指定比较器的顺序。

9、排序

1、sort(List list)
     根据元素的自然顺序 对指定列表按升序进行排序。

2、sort(List list,Comparator c)
          根据指定比较器产生的顺序对指定列表进行排序。

3、

10、换位

1、swap(List list, int i, int j)
          在指定列表的指定位置处交换元素。


11、线程同步

1、synchronizedCollection(Collection c)
          返回指定 collection 支持的同步(线程安全的)collection。

2、synchronizedList(List list)
          返回指定列表支持的同步(线程安全的)列表。

3、synchronizedMap(Map m)
          返回由指定映射支持的同步(线程安全的)映射。

4、synchronizedSet(Set s)
          返回指定 set 支持的同步(线程安全的)set。

练习:
/*
需求:使用Collections中的方法fill对List集合中的部分元素进行替换 
思路:1、将List集合中要替换的部分元素取出,并存入另一集合中 
      2、使用removeAll方法取交集
      3、用fill将要替换的元素进行替换 
      4、将取出的部分增加进集合 
*/
import java.util.*;
class  CollectionsFillTest 
{  
    public static void main(String[] args)   
    {  
        List list = new ArrayList();  
  
        list.add("abc");  
        list.add("ab");  
        list.add("abcd");  
        list.add("a");  
        list.add("abcdef");
		list.add("abcdeg");
		list.add("abcdeh");
		list.add("abcdes");
		list.add("abcdeb");
		fillSome(list,1,3,"mk");
        System.out.println(list);  
    }  
	public static void fillSome(List list,int start,int end,String key){
		if(start>=end)
			throw new InputException("要替换的元素间隔不正确");
		List li = new ArrayList();
		for(int i=start;i
Arrays工具类

一、概述

        Arrays是用于操作数组的工具类。里边的方法也全是静态的。不需要创建对象。

       把数组变成List集合的好处:可以使用集合的思想和方法来操作数组中的元素。如:containsgetindexOfsubList等方法。

二、常用方法

1、数组变集合(asList方法)

1、asList(T... a)
          将数组转换成List集合

把数组变成list集合有什么好处?
        可以使用集合的思想和方法来操作数组中的元素。
        注意:将数组变成集合,不可以使用集合的增删方法。
        因为数组的长度是固定。
        contains。
        get
        indexOf()
        subList();
        如果你增删。那么会反生UnsupportedOperationException,

练习:

import java.util.*;
class  ArraysDemo
{
	public static void main(String[] args) 
	{
		String[] arr = {"abc","cc","kkkk"};
		List list = Arrays.asList(arr);
		sop("contains:"+list.contains("cc"));
		//list.add("qq");//UnsupportedOperationException,  不能使用集合的增删方法

		sop(list);

		//int[] nums = {2,4,5};
                 
		/*
		如果数组中的元素都是对象。那么变成集合时,数组中的元素就直接转成集合中的元素。
		如果数组中的元素都是基本数据类型,那么会将该数组作为集合中的元素存在。
		*/
 Integer[] nums = {2,4,5};List li = Arrays.asList(nums);sop(li);}public static void sop(Object obj){System.out.println(obj);}}

 
        

2、集合变数组(toArray方法
/*
集合变数组。
Collection接口中的toArray方法。


*/
import java.util.*;
class  CollectionToArray
{
	public static void main(String[] args) 
	{
		ArrayList al = new ArrayList();

		al.add("abc1");
		al.add("abc2");
		al.add("abc3");
		
		/*
		1,指定类型的数组到底要定义多长呢?
		当指定类型的数组长度小于了集合的size,那么该方法内部会创建一个新的数组。长度为集合的size。
		当指定类型的数组长度大于了集合的size,就不会新创建了数组。而是使用传递进来的数组。
		所以创建一个刚刚好的数组最优。
		

		2,为什么要将集合变数组?
		为了限定对元素的操作。不需要进行增删了。

		*/

		String[] arr = al.toArray(new String[al.size()]);

		System.out.println(Arrays.toString(arr));

	}
}

小知识


一、高级for

1、格式:

        for(数据类型变量名 :被遍历的集合(collection)或者数组) {执行语句}

2、说明

        a、对集合进行遍历。只能获取集合元素。但是不能对集合进行操作。可以看作是迭代器的简写形式。

        b、迭代器除了遍历,还可以进行remove集合中元素的动作。如果使用ListIterator,还可以在遍历过程中对集合进行增删改查的操作。

3、传统for和高级for的区别:

        高级for有一个局限性。必须有被遍历的目标(集合或数组)。

        传统for遍历数组时有索引。

        建议在遍历数组的时候,还是希望使用传统for。因为传统for可以定义角标。

示例:

     
class For  
{  
    public static void main(String[] args)   
    {  
        //定义一个ArrayList集合  
        ArrayList al = new ArrayList();  
        al.add("abc1");  
        al.add("abc2");  
        al.add("abc3");  
  
        for(String s : al)  
        {  
            System.out.println(s);//用高级for遍历集合  
        }  
  
        //传统for与高级for遍历数组  
        int[] arr = {3,5,1};  
  
        for(int x=0; x hm = new HashMap();  
  
        hm.put(1,"a");  
        hm.put(2,"b");  
        hm.put(3,"c");  
  
        //keySet取出方式的高级for遍历  
        Set keySet = hm.keySet();  
        for(Integer i : keySet)  
        {  
            System.out.println(i+"::"+hm.get(i));  
        }  
  
        //entrySet取出方式的高级for遍历  
        for(Map.Entry me : hm.entrySet())  
        {  
            System.out.println(me.getKey()+"------"+me.getValue());  
        }  
  
    }  
}


 

二、方法的可变参数

        如果一个方法在参数列表中传入多个参数,个数不确定,那么每次都要复写该方法。这时可以用数组作为形式参数。但是在传入时,每次都需要定义一个数组对象,作为实际参数。在JDK1.5版本后,就提供了一个新特性:可变参数。

        可变参数其实就是数组参数的简写形式。不用每一次都手动的建立数组对象。只要将要操作的元素作为参数传递即可。隐式将这些参数封装成了数组。

        在使用时注意:可变参数一定要定义在参数列表的最后面。

示例:

    
{  
    public static void main(String[] args)   
    {  
        show("haha",2,3,4,5,6);  
    }  
    public static void show(String str,int... arr)//...就表示可变参数  
    {  
        System.out.println(arr.length);  
    }  
}   


 

三、静态导入

1、写法:

        import staticjava.util.Arrays.*;//导入的是Arrays这个类中的所以静态成员。

        import staticjava.lang.System.*//导入了Ssytem类中所以静态成员。

       没加static导入的是类,加上static导入的全是某一个类中所以的静态成员。这样写在调用该类的静态方法时可以不用再写类名。如:Arrays.sort(数组);就可以直接写sort(数组);

2、注意:

        当导入的两个类中有同名成员时,需要在成员前加上相应的类名。

       当类名重名时,需要指定具体的包名。当方法重名时,指定具体所属的对象或者类。

示例:

      
class  StaticImport //extends Object  
{  
    public static void main(String[] args)   
    {  
  
        out.println("haha");//打印输出时就可以直接省略书写System.  
        int[] arr = {3,1,5};  
  
        sort(arr);//使用Arrays工具类的方法sort时就可以省略书写Array.  
  
        int index = binarySearch(arr,1);//半分查找也是一样可以省略  
        out.println("Index="+index);  
  
        //当没有指定继承时,所以类默认继承了Object,  
       //因为toString方法都具备,所以为了区分,必须写上具体调用者  
       out.println(Arrays.toString(arr));  
    }  
}  





















你可能感兴趣的:(Java基础)