黑马程序员之集合框架2

------- <a  target="blank">android培训</a>、<a  target="blank">java培训</a>、期待与您交流! ----------

Map集合:
HashTable:底层是哈希表数据结构,是线程的同步的。不可以存储null键null值。
HashMap:底层是哈希表数据结构,是线程不同步的。可以存储null键,null值。替代了HashTable。
TreeMap:底层是二叉树结构,可以对Map集合中的键进行指定顺序的排序。


Map集合和Collection集合的区别:
Collection一次存一个元素;Map一次存一对元素。
Collection是单列集合,Map是双列集合。
Map中存储的一对元素:一个是键,一个是值。键与值之间有映射关系。
特点:要保证map集合中键的唯一性。


Map集合中共性的方法:
1,添加:
put(key,value):当存储的键相同时,新的值会替换老的值,并将老的值返回。如果键没有重复,返回null。
void putAll(Map);
2,删除:
void clear();清空集合。
value remove(key):删除指定的键。
3,判断:
boolean isEmpty();
boolean containsKey();是否包含key.
boolean containsValue();是否包含指定的值。
4:取出
int size();返回长度。
value get(key);通过指定的键获取对应的值。如果返回null,可以判断该键不存在。当然也有特殊情况,就是在hashMap集合中,是可以
存储null键,null值的。
Collection values();//获取map集合中的所有的值。

代码演示如下:

import java.util.*;
class MapDemo
{
	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");
		
		System.out.println("containsKey:"+map.containsKey("02"));
		//System.out.println("remove:"+map.remove("02"));//把02键干掉后会返回zhangsan2值。
		
		System.out.println("get:"+map.get("02"));
		
		map.put("04",null);
		System.out.println("get:"+map.get("04"));
		
		
		//获取map集合中所有的值
		Collection<String> coll=map.values();
		System.out.println(coll);
		
		System.out.println(map);//{01=zhangsan1, 03=zhangsan3}
	}
}

如果想要获取map集合中所有的元素该怎么做呢?  有两种方法:

原理:map中是没有迭代器的,collection具备迭代器,只要将map集合转成Set集合,就可以使用迭代器了。
之所以转成Set,是因为map集合具备键的唯一性,其实Set集合就来自于map,Set集合底层其实用的就是map
方法。
把map集合转成Set的方法:
Set keySet();
Set entrySet();取得是键和值的映射关系。
Entry就是Map接口中的内部接口。
为什么要定义在map内部呢?entry是访问键值关系的入口,是map的入口,访问的是map的中的键值对。
代码演示如下:

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集合中。而这个关系的数据类型就是:Map.Entry
		
		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();
			String key=me.getKey();
			String value=me.getValue();
			System.out.println(key+":"+value);
		}
		
		/*
		//先获取map集合的所有键的set集合,keySet();
		Set<String> keySet=map.keySet();
		 
		Iterator<String> it=keySet.iterator();
		while(it.hasNext())
		{
			String key=it.next();
			String value=map.get(key);
			System.out.println("key:"+key+",value:"+value);
		}
		*/
	}
}

使用集合的技巧:
看到Array就是数组结构,有脚本,查询速度很快。
看到link就是链表结构,增删速度很快,而且有特有方法。addFirst,addLast,removeFirst,removeLast,getFirst,fetLast()。
看到hash就是哈希表,就要想到哈希值,就要想到唯一性,就要想到存入该结构中的元素必须覆盖hashCode,equasl方法。
看到tree就是二叉树,就要想到排序,就要想到比较。
比较的两种方式:
一个是Comparable,覆盖CompareTo方法。
一个是Comparator,覆盖Compare方法。
LinkedHashSet,LinkedHashMap:这两个集合可以保证哈希表有存入顺序和取出顺序一致,保证哈希表有序。
集合什么时候使用?
当存储的是一个元素时,就用Collection。当存储对象之间存在着映射关系时,就用map集合。
保证唯一,就用Set。不保证唯一,就用List。

Collections:它的出现给集合操作提供了更多的可能。这个类不需要创建对象,内部提供的都是静态方法。
静态方法:
Collections.sort(lsit):对list集合进行元素的自然顺序的排序。
Collections.sert(list,new ComparetorBylen);按照指定的比较器排序。
Collections.max(list);返回的是list字典中顺序最大的元素。
int index=Collections.binarySearch(list,"zz");二分查找,返回角标。
Collections.reverseOrder();逆向反转排序。
Collections.shuffle(list);随机对list中的元素进行位置的置换。
Collections.swap(list,1,2);将1和2角标置换。
List.synchronizedList(list);将非同步集合转成同步集合的方法。


Collections和Collection的区别:
Collections是个java.util下的类,是针对集合类的一个工具类,提供了一系列静态方法,实现对集合
的查找、排序、替换、线程安全化等操作。
Collection是个java.util.下的接口,它是各种集合结构的父接口,继承于它的的接口主要有Set和List,
提供了关于集合的一些操作,如插入。删除、判断一个元素是否是其成员、遍历等。


Arrays:用于操作数组对象的工具类,里面都是静态方法。
asList方法:将数组转换成list集合。
String[] arr={"abc","kk","qq"};
List<String> list=Arrays.asList(arr);//将arr数组转成List集合。
将数组转成集合,有什么好处呢?
可以通过List集合中的方法来操作数组中的元素:isEmpty()、contains、indexOf、set。
注意:这里有一个局限性:数组是固定长度的,不可以使用集合对象增加或者删除等,会改变数组长度的功能
方法。比如add、remove、clear,会报不支持操作的异常。
如果数组存储的是引用数据类型,直接作为集合的元素可以直接使用集合中的方法。
如果数组存储的是基本数据类型,asList会将数组实体作为集合元素存在。


集合变成数组:用的是Collection接口中的toArray();
如果给toArray传递的是指定类型的数据长度小于了集合的size,那么toArray方法,会自定在创建一个该类型
的数据,长度为集合的size。
如果传递的指定的类型的数组的长度大于了集合的size,那么toArray方法,就不会创建新数组,直接使用
该数组即可,并将集合中的元素存储到数组中,其他为存储元素的位置默认值为null。
所以,在传递指定数组时,最好的方式就是指定类型的长度和size相等的数组。
将集合变成数组有什么好处?限定了堆集合中的元素进行增删操作,只要获取这些元素即可。

Collection在JDK1.5以后,有了一个父接口Iterator,这个接口的出现将iterator方法进行抽取,提高了扩展性。
增强for循环:foreach语句,简化了迭代器的书写。
格式:增强for循环括号里写两个参数,第一个是声明一个变量,第二个就是需要迭代的容器。
for(元素类型  变量名:Collection集合&数组)
{
  ......
}


高级for循环和传统for循环的区别:
高级for循环再使用时,必须要明确被遍历的目标。这个目标,可是是Collection集合或者数组,如果遍历
Collection集合,在遍历过程中还需要对元素进行操作,比如删除,需要使用迭代器。
如果遍历数组,还需要对数组元素进行操作,建议使用传统for循环,因为可以定义角标通过角标操作元素。
如果只为遍历获取,可以简化成高级for循环,它的出现为了简化书写。


集合迭代注意的问题:
在迭代集合的过程中,不能对集合进行增删操作,会报并发访问异常,可以使用迭代器的方法进行操作。
子类ListIterator有增删的方法。

在使用增强for循环时,不能对元素进行赋值。

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");		
	 	 
	 	 for(String s:al)
	 	 {
	 	 		System.out.println(s);	
	 	 }
	 	
	 	
	 	 /*
	 	 Iterator<String> it=al.iterator();
	 	 
	 	 while(it.hasNext())
	 	 {
	 	 	
	 	 		System.out.println(it.next());
	 	 }
	 	 */
	 	 
	 	 
	 	 int[] arr={3,5,1};
	 	 for(int i: arr)
	 	 {
	 	 	System.out.println("i:"+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();
	 	 for(Integer i:keySet)
	 	 {
	 	 	System.out.println(i+"::"+hm.get(i));	
	 	 }
	 	 
	 	 
	 	 //第二种方式。entrySet.
	 	 
	 	 //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());
	 	 }
	}
}

泛型:在JDK1.5版本以后出现的一个安全机制。表现格式<>
好处:
1:将运行时期的问题ClassCastException问题转换成了编译失败,体现在编译时期,程序员就可以解决
   这个问题。
2:避免了强制转换的麻烦。


只要带有<>的类或者接口,都属于带有类型参数的类或者接口,在使用这些类或者接口时,必须给<>中传递
一个具体的引用数据类型。
泛型技术:其实应用在编译时期,是给编译器使用的技术,到了运行时期,泛型就不存在了。
为什么?因为泛型的擦除,也就是说,编译器检查了泛型的类型正确后,在生成的类文件中是没有泛型的。
在运行时,是如何知道获取的元素类型而不用强转呢?
泛型的补偿,因为存储的时候,类型已经确定了是同一个类型的元素,所以在运行时,只要获取到该元素的
类型,在内部进行一次转换即可,所以使用者不用再做转换动作了。


什么时候使用泛型类呢?
当类中的操作的引用数据类型不确定的时候,以前用的Object来进行扩展,现在可以用泛型来表示。这样可以
避免强制转换的麻烦,而且将运行问题转移到了编译时期。


泛型中通配符:可以解决当具体类型不确定的时候,这个通配符就是?,当操作类型时,不要使用类型的具体
功能时,只使用Object中的功能。那么可以用?通配符来表示未知类型。
泛型的限定:
上限:?extends E可以接收E类型或者E类型的子类型对象。
下限:?super E 可以接收E类型或者E类型的父类型对象。


------- <a  target="blank">android培训</a>、<a  target="blank">java培训</a>、期待与您交流! ----------

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值