10.集合框架(三)【Map】【集合技巧】【工具类Collections】【工具类Arrays】

    

一、Map集合(接口)

1. 概述

Map集合每次都是一次添加一对元素Collection是每次添加一个元素。所以,Map集合也称为双列集合,Collection集合也称为单列集合。其实,Map集合中存储的是键值对。

Map集合中必须保证键的唯一性。一个映射不能包含重复的键,每个键最多只能映射到一个值。

在有映射关系时,可以优先考虑使用Map

2. Map集合常用方法

1)添加

value put(key,value):返回前一个和key关联的值,如果之前没有关联的值,返回

                null

2)删除

void clear():清空map集合。

valueremove(key):根据指定的key删除此键值对,并返回和key关联的值。

3)判断

boolean constainsKey(key)

boolean constainsValue(Value)

boolean isEmpty()

4)获取

Value get(key):通过键获取值,如果没有该键,则返回null.

            可以通过返回null,判断是否含有指定键。

int size():返回此映射中的键值对个数。

keyset():返回此映射中包含键的Set集合。

entrySet():返回此映射中包含的映射关系的Set集合。

Collection values():返回Map集合的所有值得Collection集合。

例子:Collection values()方法演示

<span style="font-size:18px">import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class ValuesDemo {
	public static void main(String[] args) {
		//创建集合
		Map<Integer,String> map = new HashMap();
		//调用处理方法。
		method(map);
	}

	public static void method(Map<Integer,String> map){
		//添加元素
		map.put(8, "lisi");
		map.put(2, "wangwu");
		map.put(4, "zhangsan");
		map.put(7, "zhaoliu");
		
		//调用values方法
		Collection<String> values = map.values();
		
		Iterator<String> it = values.iterator();
		while(it.hasNext()){
			System.out.println(it.next());
		}
	}
}
</span>


 

3. Map集合常用的子类

Map

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

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

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

    |--TreeMap:内部结构是二叉树,不同步。

4. 如何迭代获取Map集合中的元素?

获取Map集合元素的原理:Map集合是没有迭代器的,Collection才有迭代器。

       所以需要将Map转为Set集合。之所以转成Set,是因为Set具备唯一性,和Map

       集合的键的唯一性相符合。其实Set底层就是用Map的方法。

 

       如何将Map转为Set

1)通过keySet方法获取Map集合所有键的Set集合。迭代获取每一个键,再调用

get方法获取每一个键相应的值即可

 

<span style="font-size:18px">import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class keySetDemo {

	/**keySet()用于获得map中所有的键。可以用它来输出每个键对应的值。
	 * @param args
	 */
	public static void main(String[] args) {
		//创建集合
		Map<Integer,String> map = new HashMap();
		//调用处理方法。
		method(map);
	}

	/**方法功能:取出map中所有的元素。
	 * 原理:通过keySet方法获取map中所有键所在的Set集合。
	 * 		通过Set中的迭代器获取每一个键。
	 * 		再通过get方法对每一个键获取相应的值即可。
	 * @param map
	 */
	public static void method(Map<Integer,String> map){
		//添加元素
		map.put(8, "lisi");
		map.put(2, "wangwu");
		map.put(4, "zhangsan");
		map.put(7, "zhaoliu");
		
		//调用keySet方法,获取map中所有的键。
		Set<Integer> keyset = map.keySet();
		//调用Set中的迭代器,根据每一个键获取相关联的值
		Iterator<Integer> it = keyset.iterator();
		while(it.hasNext()){
			
			//获取键
			Integer key = it.next();
			//根据键获取值。
			String value = map.get(key);
			//打印键值对。
			System.out.println(key+":"+value);
		}
	}	
}
</span>


2)通过entrySet方法获取获取所有键值的映射关系的Set集合,这个映射关系的类型是Map.Entry.迭代获取每一个映射关系,调用getKeygetValue方法分别获取每一个映射关系的键和值。

<span style="font-size:18px">import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class entrySetDemo {
	public static void main(String[] args) {

		//创建集合
		Map<Integer,String> map = new HashMap();
		
		//调用处理方法。
		method(map);
	}
	public static void method(Map<Integer,String> map){
		
		//添加元素
		map.put(8, "lisi");
		map.put(2, "wangwu");
		map.put(4, "zhangsan");
		map.put(7, "zhaoliu");
		
		/*
		 * 通过map转成set就可以迭代。
		 * 找到了另一个方法:entrySet方法。
		 * 该方法将键和值得映射关系作为对象存储到了Set集合中。
		 * 这个映射关系的类型就是Map。Entry类型(结婚证)。
		 */
		Set<Map.Entry<Integer, String>> entrySet = map.entrySet();
		Iterator<Map.Entry<Integer, String>> it = entrySet.iterator();
		while(it.hasNext()){
			Map.Entry<Integer, String> me = it.next();
			Integer key = me.getKey();
			String value = me.getValue();
			System.out.println(key+":"+value);
		}
	}	
}
</span>


 

5. Map练习

1)"fagavacbsacdfa"获取该字符串中,每个字母出现的次数。

       要求打印结果是:a(2)b(1)...;

代码实现

      

<span style="font-size:18px">import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;

/*
 * 思路:
 * 对于结果的分析发现,字母和字数之间存在着映射关系,而且这种关系很多。
 * 很多就需要存储,能存储映射关系的容器有数组和Map集合。
 * 关系一方是有序编号吗?没有!
 * 所以可以用TreeMap。
 * 
 * 这个集合最终存储的应该是字母和次数的映射关系。
 * 
 * 1.因为操作的是字符串中的字母,所以先将字符串变成字符数组。
 * 2.遍历字符数组,用每一个字母作为键去查Map这个表。
 *   如果该字母不存在,就将该字母作为键,1为值存储到Map表中。
 *   如果该字母存在,就将该字母对应的值取出并+1,再将该字母和+1后的值存储到Map集合中。
 *   键相同值会覆盖。这样就实现记录字母出现的次数。
 * 3.遍历结束,map集合就记录所有字母出现的次数。上
 */

public class MapTest {
	public static void main(String[] args) {
		String str = "fa+g-avacAbsad  gfacDdfa";
		String s = getChar(str);
		System.out.println(s);
	}

	public static String getChar(String str) {
		//将字符串变成字符数组。
		char[] chs = str.toCharArray();
		
		//定义map集合表。
		Map<Character,Integer> map = new TreeMap<Character,Integer>();
		
		//遍历数组
		for (int i = 0; i < chs.length; i++) {
			
			//筛选,只统计字母
			if(!(chs[i]>='a' && chs[i]<='z' ||chs[i]>='A' && chs[i]<='Z')){
				continue;
			}
			//查表。
			Integer value = map.get(chs[i]);
			
			Integer count = 1;
			//判断值是否为null.
			if(value!=null){
				 count = value+1;
			}
			
			map.put(chs[i], count);
			/*
			if(value==null){
				map.put(chs[i], 1);
			}
			else{
				map.put(chs[i], value+1);
			}
			*/
		}
		return mapToString(map);
	}

	private static String mapToString(Map<Character, Integer> map) {
		
		//将结果变成字符串输出
		StringBuilder sb = new StringBuilder();
		Iterator<Character> it = map.keySet().iterator();
		while(it.hasNext()){
			Character key = it.next();
			Integer value = map.get(key);
			sb.append(key+"("+value+")");
		}
		return sb.toString();
	}
}
</span>


2)练习2Map集合练习——查表法

代码实现

<span style="font-size:18px">import java.util.HashMap;
import java.util.Map;

public class MapTest2 {
	public static void main(String[] args) {
		/*
		 *		 * 在查表法中的应用较为多见。
		 */
		
		String week = getWeek(5);
		System.out.println(week);
		
		System.out.println(getWeekByMap(week));
	}

	private static String getWeekByMap(String week) {
		
		Map<String,String> map = new HashMap<String,String>();
		
		map.put("星期一", "Mons");
		map.put("星期二", "Tues");
		map.put("星期三", "wend");
		map.put("星期四", "thus");
		map.put("星期五", "Frid");
		map.put("星期六", "Sate");
		map.put("星期日", "Sund");
		map.put("星期天", "Sund");
		
		return map.get(week);
	}
	public static String getWeek(int i) {
		String[] week = {"","星期一","星期二","星期三","星期四","星期五","星期六","星期日"};
		return week[i];
	}
}
</span>


 

二、集合的一些技巧

1) 选择哪个集合?

需要唯一吗?

需要:Set

   需要制定顺序:

       需要:TreeSet

       不需要:HashSet

       但是想要一个和存储一致的顺序(有序):LinkedHashSet

 

不需要唯一:List

   需要频繁增删吗?

       需要:LinkedList

       不需要:ArrayList

 

2) 如何记录每一个容器的数据结构和所属体系呢?

 

看名字!

List

   |--ArrayList

   |--linkedList

Set

   |--HashSet

   |--TreeSet

 

后缀名就是该集合所属体系。

前缀名就是该集合的数据结构。

看到array:就要想到数组,想到查询快,有角标。

看到link:就要想到链表,想到增删快,想到add,get,remove+firstlast方法。

看到hash:就要想到哈希表,就想到唯一性,就要想到元素需要覆盖hashcode方法和equals方法。

看到tree:就要想到二叉树,就想到排序,就要想到两个接口Comparable,Comparator.

而且通常这些常用的集合容器都是不同步的。

 

三、工具类Collections

1. 概述

Collections类是由在collection上操作或返回collection静态方法组成。不需要创建对象。

2. 常见操作

1) 排序

void sort(List<T> list);根据自然顺序对集合中的元素进行排序。

void shuffle(List<?> list);使用默认随机源对List集合中的元素进行随机排序。

void sort(List<T>lsit,Comparator<? super T> c);根据指定比较器的排序方法对List集合进行排序。

2) 查找

T max(Collection<? extendsT> coll);根据集合的自然顺序,获取指定集合中的最大元素。

T max(Collection<?extends T> coll,Comparator<? super T> comp);根据指定比较器,获取集合的最大元素。

intbinarySearch(Lsit<?extends Comparable<? super T>> list,Tkey);二分法查法查找key

3) 替换

void fill(List<? super T> list, T obj);list集合中的所有元素替换为obj

booleanreplaceAll(List<T>lsit,T oldVal,T newVal);newVal替换集合中的oldVal.

voidswap(Listlist,int i,int j);/在指定列表的指定位置处交换元素.

4) 反转

reverse(List<?>list);//反转list集合中元素的顺序。

5) 同步的集合,将非同步的集合转换为同步的集合,就是加锁。

synchronizedCollection(Collection<T>c)

synchronizedList(List<T> List)

通常常用的集合都是线程不安全的。因为要提高效率。如果多线程操作这些集合时,可以通过该工具类中的同步方法,将线程不安全的集合,转换成安全的。

给非同步的集合加锁的原理:

               

<span style="font-size:18px">List list = new ArrayList();//非同步的
list = MyCollections.synlist(list);//同步的

class MyCollections{
	public List synlist(List list){
		return new MyList(list);
	}
}
class MyList implements List{
	private List list;
	private static final Object lock = new Object();
	MyList(List list){
		this.list = list;
	}
	
public boolean add(Object obj){
		synchronized(lock){	
			return list.add(obj);
		}
	}

	public boolean remove(Object obj){
		synchronized(lock){
			return list.remove(obj);
		}
	}
}
</span>


 

   Collections类演示

   

<span style="font-size:18px">import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.TreeSet;

import p2.comparator.ComparatorByLength;

public class CollectionsDemo {

	public static void main(String[] args) {

		List<String> list = new ArrayList<String>();
		
		list.add("detasd");
		list.add("abc");
		list.add("detasd");
		list.add("cfd");
		list.add("zd");
		list.add("gtwd");
		
//		System.out.println(list);
		
		//对list集合进行指定顺序的排序。
//		Collections.sort(list);
//		System.out.println(list);
		
//		mySort(list);
//		mySort(list,new ComparatorByLength());
//		Collections.sort(list,new ComparatorByLength());
//		System.out.println(list);
		
//		demo_2();
		demo_3();
		
	}
	
	
	
	/*
	 *其他方法:
	 *1。fill(list,"cc");将集合中所有元素全部替换为cc.
	 *2.shuffle(list);随机排序集合。 
	 *
	 *3.将非同步的集合转换成同步的集合,就是加锁。
	 *	synchronizedCollection(Collection<T> c)
	 *  synchronizedList(List<T> List)
	 */	 
	public static void demo_3() {
		
		List<String> list = new ArrayList<String>();
		
		list.add("detroit");
		list.add("abc");
		list.add("za");
		list.add("hfdc");
		
		System.out.println(list);
		
		//fill方法
//		Collections.fill(list, "qnm");
		
		//shuffle方法
		Collections.shuffle(list);
		
		System.out.println(list);
	}
	
	
	
	
	
	/**
	 * 替换
	 * repalceAll(list,a,b);
	 * fill(list,a),将集合中所有的元素替换为a。
	 */
	public static void demo_2() {
		
		List<String> list = new ArrayList<String>();
		
		list.add("detasd");
		list.add("abc");
		
		System.out.println(list);
		
		//替换
		Collections.replaceAll(list, "abc", "nba");
		/*
		 * 原理:
		 * set(index,"nba");
		 * index = indexOf("abc");
		 * 整合起来:set(indexOf("abc","nba");
		 */
		System.out.println(list);
	}



	/**
	 * Collections逆序和替换。
	 */
	public static void demo_1() {
		
//		TreeSet<String> ts = new TreeSet<String>(new Comparator<String>(){
//
//			@Override
//			public int compare(String o1, String o2) {
//				
//				int temp = o2.compareTo(o1);
//				return temp;
//			}
			
			
//		});
		
		
		/*
		 * 逆序:Collections.reverseOrcer();
		 * 原理在上面注释部分。
		 */
//		TreeSet<String> ts = new TreeSet<String>(Collections.reverseOrder());
		
		//若调用比较器排序后再逆序。
		TreeSet<String> ts = new TreeSet<String>(Collections.reverseOrder(new ComparatorByLength()));
		ts.add("abc");
		ts.add("b");
		ts.add("tesd");
		ts.add("length");
		ts.add("nba");
		
		System.out.println(ts);
		
	
		
	}



	/**
	 * Collections.binarySearch(list)演示
	 * 折半和最值。
	 */
	public static void demo(){
		
		List<String> list = new ArrayList<String>();
		
		list.add("detasd");
		list.add("abc");
		list.add("detasd");
		list.add("cfd");
		list.add("zd");
		list.add("gtwd");
		
//		Collections.sort(list);
//		System.out.println(list);
		
//		int index = Collections.binarySearch(list, "bde");//index=-2,负号表示没找到。插入位置index=2-1=1.
//		
//		System.out.println("index="+index);
		
		//获取最大值。
//		String max = Collections.max(list);
		
		//获取长度最长的元素,调用比较器
		String max = Collections.max(list,new ComparatorByLength());
		System.out.println("max="+max);
		
	}
	
	
	
	/*
	 * sort(list,new ComparatorByLength());方法原理:
	 */
	public static <T > void mySort(List<T> list,Comparator<? super T> camp) {
		
		for (int i = 0; i < list.size()-1; i++) {
			
			for (int j = i+1; j < list.size(); j++) {
				
				if(camp.compare(list.get(j), list.get(j))>0){
					
//					T temp = list.get(i);
//					list.set(i,list.get(j));
//					list.set(j,temp);
					Collections.swap(list,i,j);
				}
				
			}
		}
	}
	
	/*
	 * sort(list)方法的原理:
	 * 因为sort方法能接受任意泛型的list进行比较排序,所以mySort方法也要实现这个功能。
	 * 方法中用到了compareTo方法,如果用通配符?,虽然能接受不同类型的泛型,但是通配符
	 * 是Object类型的,Object里没有定义compareTo方法,
	 * 所以只能定义泛型方法。并且该泛型必须具备比较性,要继承comparable才能调用compareTo方法。
	 */
	public static <T extends Comparable<? super T>> void mySort(List<T> list) {
		for (int i = 0; i < list.size()-1; i++) {	
			for (int j = i+1; j < list.size(); j++) {
				if(list.get(i).compareTo(list.get(j))>0){
					
					/*T temp = list.get(i);
					list.set(i,list.get(j));
					list.set(j,temp);*/
					//替代方法
					Collections.swap(list,i,j);
				}	
			}
		}	
	}
}
</span>

 

四、工具类Arrays

Arrays也是集合框架的工具类。里面全是静态方法。

1. 常见方法

List<T>asList(arr);将数组转换为集合。

   注意:

1)  可以使用集合的方法来操作数组元素,弥补数组工具类中方法不多的

               的不足。

            数组的长度是固定的,所以数组转换成集合后不能增删。

               即不能使用add()remove()clear()等改变长度的方法,否则会

               发生UnsupportedOperationException异常。

2)  如果数组中的元素都是对象,变成集合时,数组中的元素直接转为集合中的元素

3)  如果数组中的元素都是基本数据类型,那么将该数组整体作为集合中的一个元素。

 

binarySearch();二分查找方法

sort();排序方法

fill();替换方法

String toString();接收各种数组类型参数,并返回指定数组内容的字符串表现形式。

toString()方法的实现原理:

   

<span style="font-size:18px">//toString 的经典实现
	 public static String myToString(int[] a) {
	        if (a == null)
	            return "null";
	        int iMax = a.length - 1;
	        if (iMax == -1)
	            return "[]";

	        StringBuilder b = new StringBuilder();
	        b.append('[');
	        for (int i = 0; ; i++) {//中间省略判断,提高效率。不用每次判断长度。
	            b.append(a[i]);
	            if (i == iMax)
	                return b.append(']').toString();
	            b.append(", ");
	        }
	 }
</span>

 

例子:

   

<span style="font-size:18px">import java.util.Arrays;
import java.util.List;

public class ArraysDemo {

	public static void main(String[] args) {

		/*
		 * Arrays:集合框架的工具类。里面的方法都是静态的。
		 */
		
		int[] arr = {3,1,2,54,65,21};
		System.out.println(Arrays.toString(arr));//将数组变成字符串	
		demo_2();	
	}

	public static void demo_2() {
		
		/*
		 * 如果数组中的元素时对象,转成集合时,直接将数组中的元素作为集合的元素进行存储。
		 * 如果数组中的元素是基本类型数值,转成集合时,会将该整个数组作为集合的元素进行存储。
		 */
		int[] arr = {31,21,47,56};
		List<int[]> list = Arrays.asList(arr);//将数组转成集合。
		System.out.println(list);
	}

	
	public static void demo_1() {
		/*
		 * 重点掌握:List asList(数组):将数组转成集合。
		 * 好处:可以使用集合的方法操作数组元素,弥补数组工具类中方法不多的不足。
		 * 注意:数组长度是固定的,所以数组转成集合后不能增删,
		 *     即不能使用:add();remove();clear()等改变长度的方法。
		 *     否则,会发生UnsupportedOperationException异常。
		 * 	   
		 * 
		 */
		
		String[] arr = {"abc","haha","xixi"};
		
		boolean b = myContains(arr, "xixi");
		System.out.println("contains:"+b);
		
		//将数组转成集合。
		List<String> list = Arrays.asList(arr);
		
		boolean b1 = list.contains("xixi");
		System.out.println("list contains:"+b1);
	
//		list.add("hiahia");//UnsupportedOperationException,不能修改长度
		System.out.println(list);
	}

	public static boolean myContains(String[] arr,String key){
		
		for (int i = 0; i < arr.length; i++) {
			if (arr[i].equals(key)) {
				return true;
			}
		}
		return false;
	}
}
</span>

 

2. toArray——集合转成数组

集合转成数组,使用的是Collection接口的toArray方法。

1)  好处:

           集合转成数组,可以对集合中的元素操作方法进行限定,不能增删。

           建议:数组长度最好指定为集合的size.

2)  toArray方法详细解读

toArray方法需要传入一个指定类型的数组。

该如何确定数组长度呢?

   如果长度小于集合的size,那么该方法会创建一个同类且和集合相同size的数组。

              如果长度大于集合的size,那么该方法会将集合中的元素存储到指定的

           数组,多出的长度将默认为null

           

     例子:

      

<span style="font-size:18px">mport java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class ToArray {
	public static void main(String[] args) {	
		List<String> list = new ArrayList<String>();
		
		list.add("abc1");
		list.add("abc2");
		list.add("abc3");
		
		String[] arr = list.toArray(new String[3]);//集合转成数组,需要指定数组。
		System.out.println(Arrays.toString(arr));	
	}
}
</span>


             

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值