程序员_Java基础之-Map集合、集合工具类

时间:2023-02-12 12:08:28

 

Map集合:Map(k,v)该集合存储键值对,一对一对往里存,而且要保证键的唯一性。
1.添加:
put(K key,V value)
putAll(Map<? extends K,?extends V> m)
2.删除:
clear();
remove();
3.判断:
containsValue(Object value)
containsKey(Object key)
isEmpty()
4.获取:
get(Object key)
size()
values()
重点:Map集合的两种取出方式:

1.Set<k>keySet():将map中所有的键存入到Set集合中,因为Set具备迭代器,再根据get方法,获取每一个键对应的值。
Map集合的取出原理:将map集合装成set集合,再通过迭代器取出。
2.Set<Map.Entry<k,v>> entrySet():

注解:Map.Entry 其实Entry是一个接口,它是Map接口中的一个内部接口。

<span style="font-family:KaiTi_GB2312;font-size:18px;color:#333333;">interface Map
{
public static interface Entry
{
public abstract Object getKey();
public abstract Object getValues();
}
}
class HashMap implements Map
{
class Hashs implements Map.Entry
{
public Object getKey(){};
public  Object getValue(){};
}
}
</span>



Map  
|--Hashtable:底层是哈希表结构,不可以存入null键null值,该集合是同步的。JDK 1.0 效率低
|--HashMap:底层是哈希表数据结构,并允许使用null键null值,该集合不同步。JDK 1.2 效率高
|--TreeMap:底层是二叉树数据结构,线程不同步,可以用于个map集合中的键进行排序。

和Set很像。
其实Set此层就是使用了Map集合。
*/
/*Map共性方法*/


<span style="font-family:KaiTi_GB2312;font-size:18px;color:#333333;">import java.util.*;
class MapDemo
{
	public static void main(String[] args)
	{
		Map<String,String>map=new HashMap<String,String>();
		//添加元素
		map.put("01","zhangsan1");
		System.out.println(map.put("01","wangwu"));//添加元素时,如果出现添加相同的键,那么后添加的值会覆盖原有键对应的值。
													//并put方法会返回被覆盖的值。
		map.put("03","zhangsan3");
		
		System.out.println("containsKey:"+map.containsKey("022"));
		//System.out.println("remove:"+map.remove("02"));
		map.put("04",null)
		System.out.println("get:"+map.get("04"));
		//可以通过get方法的返回值来判断一个键是否存在。通过返回空来判断。




		//获取map集合中所值有的
		Collection <String> coll=map.values();//valuse()方法返回Collection集合类型值,该集合要指定泛型。
		System.out.println(coll);
		System.out.println(map);


	}
}
</span>

//keySet()方法:


<span style="font-family:KaiTi_GB2312;font-size:18px;color:#333333;">import java.util.*;
class MapDemo2
{
	public static void main(String[] args)
	{
		Map<String,String> map=new HashMap<String,String>();
		map.put("02","zhangsan2");
		map.put("03","zhangsan3");
		map.put("01","zhangsan1");
		map.put("04","zhangsan4");


		//将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();//Map.Entry<>类,可理解为关系,有getKey(),getvalue()方法。


			String key=me.getKey();
			String value=me.getValue();
			System.out.println(key+":"+value);
		}






/*


		//获取map集合的所有键的Set集合,keySet();
		Set<String> keySet=map.keySet();
		//有了Set集合,就可以获取器迭代器。


		Iterator<String> it=keySet.iterator();
		while(it.hasNext())
		{
			String key=it.next();
			String value=map.get(key);
			System.out.println("key:"+key);
			//有了键,就可以通过map集合的get方法获取其对应的值


			System.out.println("key:"+key+",value"+value);
		}
*/
		
	}
}</span>


/*每一个学生都有相应的归属地。
学生Student,地址String
学生属性:姓名,年龄。
注意:姓名和年龄相同的学生视为同一个学生。
保证学生唯一性。
1.描述学生。
2.定义map容器,将学生作为键,地址作为值,存入。
3.获取map集合中的元素。
*/
<span style="font-family:KaiTi_GB2312;font-size:18px;color:#333333;">import java.util.*;
class Student implements Comparable<Student>
{
	private String name;
	private int age;
	Student(String name,int age)
	{
		this.name=name;
		this.age=age;
	}
	public int compareTo(Student s)//复写compareTo()方法,实现Comparable是因为,学生类可能储存到TreeSet中。
	{
		int num=new Integer(this.age).compareTo(new Integer(s.age));//将年龄封箱成Integer类,使其调用compareTo方法,进行比较
		if(num==0)
				return this.name.compareTo(s.name);
		return num;
	}
	public int hashCode()//复写hashCode(),equals(),是因为学生有可能储存到hashSet中。
	{
		return name.hashCode()+age*34;
	}
	public boolean equals(Object obj)
	{
		if(!(obj instanceof Student))
			throw new ClassCastException("类型不匹配");
		Student s=(Student)obj;
		return this.name.equals(s.name) && this.age==s.age;


	}
	public String getName()
	{
		return name;
	}
	public int getAge()
	{
		return age;
	}
	public String toString()
	{
		return name+":"+age;
	}






}
class MapTest
{


	public static void main(String[] args)
	{
		HashMap<Student,String> hm=new HashMap<Student,String>();
		hm.put(new Student("lisi1",21),"beijing");
		hm.put(new Student("lisi1",21),"tianjin");
		hm.put(new Student("lisi3",23),"nanjing");
		hm.put(new Student("lisi4",24),"wuhan");


		//第一种取出方式 keySet
		Set<Student> keySet =hm.keySet();
		Iterator<Student> it=keySet.iterator();
		while(it.hasNext())


		{
			Student stu =it.next();
			String addr=hm.get(stu);
			System.out.println(stu+"..."+addr);
		}


//第二种取出方式 entrySet


		Set<Map.Entry<Student,String>> entrySet=hm.entrySet();
		Iterator <Map.Entry<Student,String>> iter = entrySet.iterator();
		while(iter.hasNext())
			{
				Map.Entry<Student,String> me=iter.next();
				Student stu=me.getKey();
				String addr=me.getValue();
				System.out.println(stu+"........"+addr);
			}




		
	}
}
</span>

/*需求:对学生对象的姓名进行升序排序
因为数据是以键值对形式存在的。所以要使用可以排序的Map集合,TreeMap
另外:因为Student类中compareTo方法已经固定,故使用比较器Comparator。
*/
<span style="font-family:KaiTi_GB2312;font-size:18px;color:#333333;">import  java.util.*;
class StuNameComparator implements Comparator<Student>
{


	public int cmopare(Student s1,Student s2)
	{
		int num=s1.getName().compareTo(s2.getName());
		if(num==0)
			return new Integer(s1.getAge()).compareTo(new Integer(s2.get.Age()));
		return num;
	}
}
class MapTest2
{
	public static void main(String[] args)
	{
		TreeMap<Student,String> tm=new TreeMap<Student,String>(new StuNameComparator());
		tm.put(new Student("blisi3",23),"nanjing");
		tm.put(new Student("lisi1",21),"beijing");
		tm.put(new Student("1lisi4",24),"wuhan");
		tm.put(new Student("blisi2",22),"shanghai");
		
		Set<Student> entrySet =tm.entrySet();
		Iterator<Map.Entry<Student,String>> it=entrySet.iterator();
		while(it.hasNext())


		{
			Map.Entry<Student,String >me =it.next();
			Student stu=me.getKey();
			String addr=me.getValue();
			System.out.println(stu+"..."+addr);
		}
	}
}
</span>

/*练习:
“addfagjgajghe”获取该字符串中的字母出现的次数。
希望打印结果: a(1)c(2)...

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

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

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

思路:
1.将字符串转换成字符数组,因为要对每一个字母进行操作。
2.定义一个map集合,因为打印结果的字母有顺序,所以使用treemap集合。
3.遍历字符数组。
将每一个字母作为键去查map集合。
如果返回null,将该字母和1存入到map集合中。
如果返回不是null,说明该字母在map集合已经存在,并有对应次数。
那么就获取该次数并进行自增,然后将该字母和自增后的次数存入到map集合中--覆盖掉原来键对应的值。
4.将map集合中的数据变成指定的字符串形式返回


*/

<span style="font-family:KaiTi_GB2312;font-size:18px;color:#333333;">import java.util.*;
class MapTest3
{
	public static void main(String[] args)
	{
		String s=charCount("aabfcdabcdefa");
		System.out.println(s);
	}
	public static String charCount(String str)
	{
		char[] chs=str.toCharArray();
		TreeMap<Character,Integer> tm=new TreeMap<Character,Integer>();
				//!!!泛型类中接受的都是引用数据类型,所以必须转换成对应的包装类
		for(int x=0;x<chs.length;x++)
		{
			if(!(chs[x]>='a' && chs[x]<='z'||chs[x]>='A' && chs[x]<='Z'))
				continue;//如果不是字母,继续循环。
			Integer value=tm.get(chs[x]);
			if(value==null)
			{
				tm.put(chs[x],1);
			}
			else
			{
				value=value+1;
				tm.put(chs[x],value);
			}
		}
		//System.out.println(tm);
		//return null;
		StringBuilder sb=new StringBuilder();
		Set<Map.Entry<Character,Integer>> entrySet=tm.entrySet();
		Iterator<Map.Entry<Character,Integer>> it=entrySet.iterator();


		while(it.hasNext())
		{
			Map.Entry<Character,Integer> me=it.next();
			Character ch=me.getKey();
			Integer value=me.getValue();
			sb.append(ch+"("+value+")");
		}
		return sb.toString();
	}
}
</span>



/*map扩展知识。
map集合被使用是因为具备映射关系。
一个学校有多个教室,每一个教室都有名称。


*/
<span style="font-family:KaiTi_GB2312;font-size:18px;color:#333333;">import java.util.*;
class Student
{
	private String id;
	private String name;
	Student(String id,String name)
	{
		this.id=id;
		this.name=name;
	}
	public String toString()
	{
		return id+":::"+name;
	}
}
class MapDemo3
{
	public static void demo()
	{
		HashMap<String,List<Student>> czbk=new HashMap<String,List<Student>>();
		List<Student> reyu=new ArrayList<Student>();
		List<Student> jiuye=new ArrayList<Student>();
		czbk.put("yureban",reyu);
		czbk.put("jiuyeban",jiuye);


		reyu.add(new Student("01","zhangsan"));		
		reyu.add(new Student("04","wangwu"));
		jiuye.add(new Student("01","zhouqi"));
		jiuye.add(new Student("02","zhaoli"));


	Iterator<String> it=czbk.keySet().iterator();
	while(it.hasNext())
		{
			String roomName=it.next();
			List<Student> room=czbk.get(roomName);


			System.out.println(roomName);
			getInfos(room);
	
		}


  }
	public static void getInfos(List<Student> list)
	{
		Iterator<Student> it=list.iterator();
		while(it.hasNext())
		{
			Student s=it.next();
			System.out.println(s);
		}
	}
	public static void main(String[] args)
	{
		demo();
	}
}</span>

集合框架的工具类Collections
sort():
public static <T extends Comparable<? super T>>void sort(List<T> list)
{}

<span style="font-family:KaiTi_GB2312;font-size:18px;color:#333333;">import java.util.*;
class CollectionsDemo
{
	public static void main(String[] args)
	{
		/*
		sortDemo();
		maxDemo();
		binarySearchDemo();
		fillDemo();
		//binarySearchDemo
		*/
		replaceAllDemo();
	}
	public static void sortDemo()//对list进行排序
	{
		List<String> list=new ArrayList<String>();
		list.add("abcd");
		list.add("aaa");
		list.add("kkkkk");
		list.add("qq");
		
		sop(list);


		Collections.sort(list/*,new StrLen_Comparator()*/);//Collections工具类的排序方法。可用比较器




		sop(list);
	}
public static void maxDemo()//list中的最大值
	{
		List<String> list=new ArrayList<String>();
		list.add("abcd");
		list.add("aaa");
		list.add("kkkkk");
		list.add("qq");
		
		sop(list);
		String max=Collections.max(list/*,new StrLen_Comparator()*/);
		sop("max="+max);
	}
	public static void binarySearchDemo()//对某元素进行二分查找
	{
		List<String> list=new ArrayList<String>();
		list.add("abcd");
		list.add("aaa");
		list.add("kkkkk");
		list.add("qq");
		
		sop(list);
		int index=Collections.binarySearch(list,"aaa",new StrLen_Comparator());
												//返回负数,说明不存在。可用比较器
		sop("index="+index);


	


	}
public static void shuffleDemo()//对集合中元素进行随机打乱。
	{
		List<String> list=new ArrayList<String>();
		list.add("abcd");
		list.add("aaa");
		list.add("kkkkk");
		list.add("qq");
		
		sop(list);
		Collections.shuffle(list);
		sop(list);
	}
public static void fillDemo()
	{
		List<String> list=new ArrayList<String>();
		list.add("abcd");
		list.add("aaa");
		list.add("kkkkk");
		list.add("qq");
		
		sop(list);
		Collections.fill(list,"p");//集合中元素替换成指定元素。
		sop(list);
	
	}
/*练习:fill方法可以将list集合中所有的元素替换成指定元素。怎么将list集合中部分元素替换成指定元素呢?*/
public static void replaceAllDemo()
	{
		List<String> list=new ArrayList<String>();
		list.add("abcd");
		list.add("aaa");
		list.add("kkkkk");
		list.add("qq");
		
		sop(list);
		Collections.replaceAll(list,"aaa","ppp");
		sop(list);
		Collections.reverse(list);
		sop(list);
	}
public static void sop(Object obj)
	{
		System.out.println(obj);
	}
}
class StrLen_Comparator implements Comparator<String>//当 对Collections工具类中的默认排序方法不满意时,
													//可以定义自己的排序方法,只要实现比较器Comparator接口,重写comapre方法即可。


{
	public int compare(String s1,String s2)
	{
		if(s1.length()>s2.length())
			return 1;
		if(s1.length()<s2.length())
			return -1;
		return s1.compareTo(s2);//当两字符相等时,进行默认的字典比较。
	}
}
</span>


/*Collections-reverseOrder()*/
<span style="font-family:KaiTi_GB2312;font-size:18px;color:#333333;">import java.util.*;
class CollectonsDemo2
{
	public static void main(String[] args)
	{
		orderDemo();
	}
	public static void orderDemo()
	{
		TreeSet<String> ts=new TreeSet<String>(Collections.reverseOrder());//Collectons.reverseOrder()方法,可将系统默认的比较方法产生的自然顺序反转。
	///	TreeSet<String> ts=new TreeSet<String>(Collections.reverseOrder(new StrComparator()));//Collectons.reverseOrder(比较器)方法,可以将现有的比较器产生的顺序,强行反转。


		ts.add("abcde");
		ts.add("aaa");
		ts.add("k");
		ts.add("cccccc");


		Iterator it=ts.iterator();
		while(it.hasNext())
		{
			System.out.println(it.next());
		}


	}
}</span>


/*集合工具类:Arrays
用于操作数组的工具类,里面都是静态方法。
*/
/*asList:将数组变成list集合。 */


<span style="font-family:KaiTi_GB2312;font-size:18px;color:#333333;">import java.util.*;
class ArraysDemo
{
	public static void main(String[] args)
	{
	//	int[] arr={2,4,5};
	//	System.out.println(Arrays.toString(arr));//原来数组变字符串方法。


	String[] arr={"abc","cc","kkk"};
	//把数组变成list集合有什么好处???
	/*可以使用集合的思想和方法来操作数组中的元素。
	注意:将数组变成集合,不可以使用集合的增删方法,因为数组的长度时固定的。
		可用contains,get,indexOf(),subList()等等方法。
		
		如果增删,那么会发生UnsupportedOperationExc。
	*/


	List<String> list=Arrays.asList(arr);//将数组变成集合
	sop("contains:"+list.contains("cc"));
	//list.add("qq");//UnsupportedOperatorExc
	sop(list);




	int[] nums={2,3,5};
	List li=Arrays.asList(nums);
	sop(li);//输出结果为数组的地址,而不是数组中元素。
	/*如果数组中的元素都是基本数据类型,那么会将该数组作为集合中的元素存在
		如果数组中的元素都是对象,那么变成集合时,数组中的元素就直接转成集合中的元素。
		所以可写成以下形式:
	*/
	Integer[] nums2={2,4,5};
	List<Integer>li2=Arrays.asList(nums2);
	sop(li2);
	}
	public static void sop(Object obj)
	{
		System.out.pritln(obj);
	}
}
</span>






/*集合转成数组
Collection接口中的toArray方法。
*/
<span style="font-family:KaiTi_GB2312;font-size:18px;color:#333333;">import java.util.*;
class CollectionToArray
{
	public static void main(String[] args)
	{
		ArrayList<String> al=new ArrayList<String>();
		al.add("abc1");
		al.add("abc2");
		al.add("abc3");


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


		2.为什么要将集合变数组。
		为了限定对元素的操作。不需要进行增删了。
		*/
		String[] arr=al.toArray(new String[al.size()]);//new String[al.size()]:创建存储该集合元素的数组,并指定大小。


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


	}
}
</span>




/*增强for循环
格式:
for(数据类型 变量名:被遍历的集合(Collection)或者数组)
{
}


对集合进行遍历,只能获取集合元素,但是不能对集合进行操作。


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


传统for和高级for有什么区别呢??


高级for有一个局限性,必须有被遍历的目标。
建议在遍历数组时,还是希望用传统for,因为传统for可以定义角标。
*/
<span style="font-family:KaiTi_GB2312;font-size:18px;color:#333333;">	import java.util.*;
	class ForEachDemo
	{
		public static void main(String[] args)
		{
			ArrayList<String> al=new ArrayList<String>();
			al.add("abc1");
			al.add("abc2");
			al.add("abc3");
			/* 
			JDK1.2-1.4都是用迭代器
			Iterator<String> it=al.iterator();
			while(it.hasNext())
			{
				System.out.println(it.next());
			}
			*/
			/*JDK1.5以后用高级for循环*/
			for(String s:al)
			{
				System.out.println(s);
			}


			int[] arr={3,5,1};
			for(int i:arr)
			{
				System.out.println(i);
			}
		HashMap<Integer,String> hm=new HashMap<Integer,String>();


		hm.put(1,"a");
		hm.put(2,"b");
		hm.put(3,"c");


		Set<Integer> keySet=hm.keySet();//将键值存入Set集合
		for(Integer i:keySet)
			{
				System.out.println(i+"::"+hm.get(i));
			}
		//Set<Map.Entry<Integer,String>> entrySet=hm.entrySet();
		//for(Map.Entry<Integer,String>) me:entrySet)相当于以下语句:
		for(Map.Entry<Integer,String> me : hm.entrySet())
			{
				System.out.println(me.getKey()+"---"+me.getValue());
			}


			
		}
	}
</span>



/*可变参数
JDK1.5版出现的新特性。
方法的可变参数。
在使用时注意:
!!可变参数一定要定义参数数列表最后面。
*/
<span style="font-family:KaiTi_GB2312;font-size:18px;color:#333333;">class ParamMethodDemo
{
	public static void main(String[] args)
	{
	
		/*每次定义一个数组,作为实际参数
		int[]arr={3,4};
		show(arr);


		int[] arr1={3,5,6,6};
		show(arr1);*/
		/*
			可变参数:
			其实就是上一中数组参数的简写形式。
			不用每一次都手动的建立数组对象。
			只要将要操作的元素作为参数传递即可。
			隐式将这些参数封装成了数组。
		*/
		show("hahahah",2,3,5,6);//可变参数会把2,3,5,6隐式封装成数组
	}
	public static void show(String str,int....arr)//...为可变参数,int...arr为数组
	{
		System.out.println(arr.length);
	}
}</span>


/*StaticImport  静态导入


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


<span style="font-family:KaiTi_GB2312;font-size:18px;color:#333333;">import java.util.*;
import static java.util.Arrays.*://“static”,导入的是Arrays这个类中的所有静态成员。
import static java.lang.System.*;//导入了System类中所有静态成员。
class StaticImport
{
	public static void main(String[] args)
	{
		int[] arr={3,1,5};
		//Arrays.sort(arr);Arrays可省略,写成sort(arr)
		sort(arr);
		int index=binarySearch(arr,1);
		out.println(Arrays.toString(arr));//此处省去System. ,另外toString()前的Arrays不可省,因为本类是继承Object类,Object中也有此方法
		.out.println("Index="+index);
	}
}</span>