黑马程序员_毕向东JAVA基础_集合(3)Map&Collections&Arrays&增强for循环

------- android培训java培训、期待与您交流! ----------

(一)Map集合

该集合存储键值对。一对一对往里存。而且要保证键的唯一性。


1.Map与Collection的区别:

Map与Collection在集合框架中属并列存在。Map存储的是键值对,Map存储元素使用put方法,而Collection使用add方法。

Map集合没有直接取出元素的方法,而是先转成Set集合,再通过迭代获取元素。Map集合中键要保证唯一性。

2.Map集合常用方法

1.添加

        put(K key,V value);

putAll(Map<? extends K,?extends V> m);

//注意:put方法,如果key已经存在,则新存入的值覆盖原来的值,并把原来的值作为方法的返回值;

add方法,如果该元素已经存在,则不能存入集合,方法返回false,如果不存在,则存入集合,方法返回值为true。

2.删除

clear()

V remove(Object key)

3.判断

boolean containsKey(Object key)

boolean containsValue(Object value)

boolean isEmpty()

4.获取

V get(Object key)

int size()

Collection<V> values()

Set<Map.Entry<K,V>> entrySet()

Set<K> keySet()

3.Map体系结构

          |--Hashtable:底层是哈希表数据结构,不可以存入null键,null值。该集合时线程同步的。JDK1.0,效率低。

          |--HashMap:底层是哈希表数据结构。允许使用null键和null值。该集合是线程不同步的。JDK1.2,效率高。

         |--TreeMap:底层是二叉树数据结构。线程不同步。可以用于该Map集合中的键进行排序。


4.Map集合与Set集合

其实Set集合底层就是使用了Map集合。

1.keySet:将Map中所有的键存入到Set集合,因为set具备迭代器。

     所以可以迭代方式取出所有的键,再根据get方法获取每一个键对应的值。

                    Map的取出原理:将Map集合转成Set集合,再通过迭代器取出。


2.Set<Map.Entry<k,v>>  entrySet():

将map集合中的映射关系存入到了Set集合中。而这个关系的数据类型就是:Map.Entry

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

因为Entry代表关系,先有Map集合,才能有关系并且Entry代表的是Map集合中的关系。所以Entry定义在Map的内部。


代码示例(一):put方法及其返回值

import java.util.*;
class MapDemo 
{
	public static void main(String[] args) 
	{
		//用泛型确定结合中对象的类型。
		Map<String,String> map = new HashMap<String,String>();

		//添加元素,如果出现添加时,相同的键,那么后添加的值会覆盖原有键对应值。
		//并put方法会返回被覆盖的值。
		System.out.println("put:"+map.put("01","zhangsan1"));
		System.out.println("put:"+map.put("01","wangwu"));
		map.put("02","zhangsan2");
		map.put("03","zhangsan3");

		System.out.println("comtainsKey:"+map.containsKey("022"));
		//System.out.println("remover:"+map.remove("02"));
		System.out.println("get:"+map.get("02"));
		System.out.println(map);

		//注意:可以通过get方法的返回值来判断一个键是否存在。通过返回null来判断。
		//map.put(null,"ddddd");
		//System.out.println("get:"+map.get(null));

		//获取map集合中的所有的值
		Collection<String> coll = map.values();
		System.out.println(coll);
		System.out.println(map);


		
	}
}
代码示例(二)keySet & entrySet

/*
1.keySet():将Map中所有的键存入到Set集合,因为set具备迭代器。
		   所以可以迭代方式取出所有的键,再根据get方法获取每一个键对应的值。
2.entrySet();2.Set<Map.Entry<k,v>>  entrySet():将map集合中的映射关系存入到了Set集合中。
            而这个关系的数据类型就是:Map.Entry
*/
import java.util.*;
class MapDemo2 
{
	public static void main(String[] args) 
	{
		Map<String,String> map = new HashMap<String,String>();
		map.put("01","zhangsan1");
		map.put("02","zhangsan2");
		map.put("03","zhangsan3");
		map.put("04","zhangsan4");
		//1.keySet()
		//先获取Map集合的所有键的Set集合,keySet();
		Set<String> keySet = map.keySet();
		//有了Set集合,就可以获取其迭代器
		Iterator<String> it = keySet.iterator();
		while (it.hasNext())
		{
			String key = it.next();
			//有了键可以通过map集合的get方法获取其对应的值
			String value = map.get(key);
			System.out.println("key:"+key+",value="+value);
		}
		//2.entrySet()

		Set<Map.Entry<String,String>> entrySet = map.entrySet();
		Iterator<Map.Entry<String,String>> it1 = entrySet.iterator();
		while (it1.hasNext())
		{
			Map.Entry<String,String> me = it1.next();
			System.out.println(me.getKey()+"//"+me.getValue());
		}
		
	}
}

代码示例(三)练习

/*
练习:“advddkdkdallalafjka”获取该字符串中的字母出现的次数。
希望打印结果:a(1)(2)。。。
通过结果发现,每一个字母都有对应的次数。说明字母和次数
之间都有映射关系。
注意:当发现有映射关系时,可以选择map集合。因为map集合中
存放的就是映射关系。

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

思路:
1.将字符串转成字符数组,因为要对每一个字母进行操作。
2.定义一个map集合,因为打印结果的字母有顺序,所以使用TreeMap集合。
3.遍历字符数组:
	将每一个字母作为键去查map集合。
	如果返回null,将该字母和1存入到map集合中,
	如果返回不是null,说明该字母在map集合已经存在并有对应次数。
	那么就获取该次数并进行自增,然后将该字母和自增后的次数存入到TreeMap集合中
4.将TreeMap集合中的数据变成指定的字符串形式返回。
*/
import java.util.*;
class MapTest3 
{
	public static void main(String[] args) 
	{
		System.out.println(charCount("aaddedkkkferedhjdhllladinn"));
	}

	public static String charCount(String str)
	{
		char[] chs = str.toCharArray();
		TreeMap<Character,Integer> tm = new TreeMap<Character,Integer>();
		for (int i = 0;i < chs.length ; i++ )
		{
			Integer value =tm.get(chs[i]);
			if (value == null)
			{
				tm.put(chs[i],1);
			}
			else 
			{
				value = value + 1;
				tm.put(chs[i],value);
			}
		}
		//定义一个容器,用于存储要输出结果及格式。
		StringBuilder sb = new StringBuilder();
		//定义一个Set集合,指向的是字符与数组的关系封装成的对象。
		Set<Map.Entry<Character,Integer>> mapEntry = tm.entrySet();
		Iterator<Map.Entry<Character,Integer>> it = mapEntry.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();
	}
}

代码示例(四)TreeMap

/*
需求:对学生对象的年龄进行升序排序。

因为数据是以键值对的形式存在的,
所以要使用可以排序的Map集合:TreeMap
*/
import java.util.*;

//定义一个比较器,实现Comparator接口,重写compare方法。
class StuNameCompatator implements Comparator<Student>
{
	public int compare(Student s1,Student s2)
	{
		int num = s1.getName().compareTo(s2.getName());
		if (num == 0)
		{
			return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
		}
		return num;

	}
}
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)
	{
		int num = new Integer(this.age).compareTo(new Integer(s.age));
		if (num == 0)
		{
			return this.name.compareTo(s.name);
		}
		return num;
	}
	public String getName()
	{
		return this.name;
	}
	public int getAge()
	{
		return this.age;
	}

	//将姓名和年龄封装为一个对象。
	public String toString()
	{
		return this.name+":"+this.age;
	}
}
class TreeDemo1 
{
	public static void main(String[] args) 
	{
		TreeMap<Student,String> tm = new TreeMap<Student,String>(new StuNameCompatator());

		tm.put(new Student("lisi1",21),"Beijing");
		tm.put(new Student("lisi2",25),"tianjin");
		tm.put(new Student("lisi3",23),"shanghai");
		tm.put(new Student("lisi4",24),"chongqing");
		tm.put(new Student("lisi3",25),"shanghai");
		//定义一个Set集合,指向Student和地址的关系封装成的对象。
		Set<Map.Entry<Student,String>> 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);
		}

	}
	
}

5.Map扩展知识

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

代码示例:(集合嵌套)

import java.util.*;
class MapTest2 
{
	public static void main(String[] args) 
	{
		//初始化一个HashMap集合,键是String类型,值是一个HashMap
		HashMap<String,HashMap<String,String>> czbk = new HashMap<String,HashMap<String,String>>();
		HashMap<String,String> yure = new HashMap<String,String>();
		//初始化一个HashMap集合,键和值都是String类型。
		HashMap<String,String> jiuye = new HashMap<String,String>();

		czbk.put("yureban",yure);
		czbk.put("jiuyeban",jiuye);

		yure.put("01","zhangsan");
		yure.put("02","lisi");

		jiuye.put("01","wangwu");
		jiuye.put("02","wangddd");
		//定义一个迭代器指向是czbk集合的键。		
		Iterator<String> it = czbk.keySet().iterator();
		while (it.hasNext())
		{
			String room = it.next();
			//定义一个新集合,指向czbk集合中,键对应的值(因为czbk中的值也是一个集合),
			HashMap<String,String> roomMap = czbk.get(room);
			//嵌套循环,小圈,定义迭代器指向新集合中的键
			Iterator<String> it1 = roomMap.keySet().iterator();
			while (it1.hasNext())
			{
				//取出键
				String id =it1.next();
				//取出键所对应的值。
				String name = roomMap.get(id);
				System.out.println(id+":"+name);
			}
		}				
	}
}

(二)Collections类:集合框架的工具类,里面定义的都是静态方法。

Collections和Collection有什么区别?

Collection

   是集合框架中的一个顶层接口,它里面定义了单列集合的共性方法。

   它有两个常用的子接口,

       List:对元素都有定义索引。有序的。可以重复元素。

       Set:不可以重复元素。无序。

Collections

   是集合框架中的一个工具类。该类中的方法都是静态的

   提供的方法中有可以对list集合进行排序,二分查找等方法。

   通常常用的集合都是线程不安全的。因为要提高效率。

   如果多线程操作这些集合时,可以通过该工具类中的同步方法,将线程不安全的集合,转换成安全的。


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

sort(List<T> list, Comparator<? superT> c)
          根据指定比较器产生的顺序对指定列表进行排序。

max(Collection<? extendsT> coll)
          根据元素的自然顺序,返回给定 collection 的最大元素。

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

binarySearch(List<? extends Comparable<? superT>> list, T key)
          使用二分搜索法搜索指定列表,以获得指定对象。

binarySearch(List<? extendsT> list, T key, Comparator<? superT> c)
          使用二分搜索法搜索指定列表,以获得指定对象。

注:要想用binarySearch必须是有序集合。

fill(List<? superT> list, T obj)
          使用指定元素替换指定列表中的所有元素。

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

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

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

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

代码示例:(二叉树)

/*
模拟二叉树查找字符串集合中的字符串。
*/

import java.util.*;
class  CollectionsDemo2
{
	public static void main(String[] args) 
	{
		sortDemo();
	}
	public static void sortDemo()
	{
		List<String> list = new ArrayList<String>();
		list.add("abcd");
		list.add("ava");
		list.add("tank");
		list.add("fbcdd");
		list.add("d");
		list.add("bc");
		sop(list);
		//由于二叉树查找,只能查有序的集合。对集合进行自然排序。
		Collections.sort(list);// 根据元素的自然顺序 对指定列表按升序进行排序。
		//Collections.sort(list,new StrLenComparator());//根据指定比较器进行排序
		sop(list);
		int index = halfSearch(list,"d");
		sop("index="+index);
		int in = Collections.binarySearch(list,"d");
		sop("in="+in);


	}
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
   //自定义二叉树查找方法。
	public static int halfSearch(List<String>list,String key)
	{
		int max,min,mid;
		min = 0;
		max = list.size() - 1;
		while (min <= max)
		{
			mid = (max + min)>>1;//  /2;
			String str = list.get(mid);//获取中间的字符串对象
			int num = str.compareTo(key);//调用compareTo方法比较字符串与要查找的字符串。
			if(num > 0)
				max = mid -1 ;
			else if (num < 0)
				min = mid + 1 ;
			else
				return mid;			
		}
		return -1;//找不到返回-1
		//return min;//要插入的位置。binarySearch返回的就是-min-1;
	}
}

代码示例:(降序排列)

import java.util.*;
//自定义一个比较器,实现comparator接口。
class StrComparator implements Comparator<String>
{
	public int compare(String s1,String s2)
	{
		return s2.compareTo(s1);
	}
}
class CollectionsDemo3
{
	public static void main(String[] args) 
	{
		orderDemo();
	}
	public static void orderDemo()
	{
		//TreeSet<String> ts = new TreeSet<String>(new StrComparator());
		TreeSet<String> ts = new TreeSet<String>(Collections.reverseOrder());
		ts.add("avddd");
		ts.add("ddd");
		ts.add("vdd");
		ts.add("mvddd");
		Iterator<String> it = ts.iterator();
		while (it.hasNext())
		{
			sop(it.next());
		}

	}
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
}

代码示例(练习题)

/*
练习:fill方法可以将list集合中所有元素替换成指定元素。
将list集合中部分元素替换成指定元素。
*/

import java.util.*;
class TestDemo 
{
	public static void main(String[] args) 
	{
		List<String> list = new ArrayList<String>();
		list.add("aaaaa");
		list.add("bbbbb");
		list.add("ccccc");
		list.add("ddddd");
		list.add("fffff");
		fillDemo(list,"dd",1,2);//将list集合中部分元素替换。
		//Collections.fill(list,"mm",2,3);
		
	}
	public static void fillDemo(List<String> list,String str,int start,int end)
	{
		//调用list中的subList方法。
		List<String> sublist = list.subList(start,end);
		//将sublist中全部替换为str。
		Collections.fill(sublist,str);
		sop(list);
	}
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}	
}

(三)Arrays:用于操作数组的工具类。

asList(T... a)
          返回一个受指定数组支持的固定大小的列表。

注意:将数组变成list集合,可以使用集合的思想和方法来操作数组中的元素,但是不可以使用集合的增删方法,因为数组的长度是固定的。

如果增删,会发生UnsupportedOperationException异常。

  集合变数组: collection接口中的toArray方法。

指定类型的数组到底要定义多长呢?

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

为什么要将集合变数组呢?

为了限定对元素的操作。

(四)增强for循环。

格式:

for(数据类型 变量名:被遍历的集合(Collection)或者数组)

{

}

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

 

         传统for循环与高级for循环的区别:高级for有一个局限性,必须有被遍历的目标。

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

代码示例:

import java.util.*;
class ForDemo 
{
	public static void main(String[] args) 
	{
		//遍历ArrayList集合。
		ArrayList<String> al = new ArrayList<String>();
		al.add("abc1");
		al.add("abc2");
		al.add("abc3");

		for (String s : al )
		{
			System.out.println(s);
		}

		//遍历数组
		int[] arr = {1,2,3};
		for(int i:arr)
		{
			System.out.println(i);
		}

		//去Map集合元素
		HashMap<Integer,String> hm =new HashMap<Integer,String>();
		hm.put(1,"lisi1");
		hm.put(2,"lisi2");
		hm.put(3,"lisi3");
		//keySet方式
		Set<Integer> keySet = hm.keySet();
		for(Integer index : keySet)
		{
			System.out.println(index+"..."+hm.get(index));
		}
		//entrySet方式
		Set<Map.Entry<Integer,String>> entrySet = hm.entrySet();
		for(Map.Entry<Integer,String> me : entrySet)
		{
			System.out.println(me.getKey()+"::"+me.getValue());
		}
	}
}

(五)

JDK 1.5版本出现的新特性:

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

StaticImport:静态导入。

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

importstatic java.util.Arrays.*;//导入的是Array中所有的静态成员。

代码示例:(可变参数)

class ArrDemo 
{
	public static void main(String[] args) 
	{
		show(1,3,4);
	}
	public static void show(int... arr)//可变参数,隐式将参数封装成对象
	{
		System.out.println(arr.length);
		System.out.print("[");
		for (int i = 0; i < arr.length ; i++ )
		{
			System.out.print(arr[i]+",");
		}
		System.out.println("]");
	}
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值