泛型的好处:
1: 将运行时期的问题 ClassCastException 问题转换成了编译失败,体现在编译时期,程序员就可以解决问题。
2: 避免了强制转换的麻烦。
什么时候用泛型类呢?
当类中的操作的引 用数据类型不确定的时候, 以前用的 Object 来进行扩展的, 现在可以用泛型来表示。 这
样可以避免强转的麻烦, 而且将运行问题转移到的编译时期。
泛型在程序定义上的体现:
泛型类: 将泛型定义在类上。
当方法操作的引 用数据类型不确定的时候, 可以将泛型定义在方法上。
静态方法上的泛型: 静态方法无法访问类上定义的泛型。 如果静态方法操作的引 用数据类型不确定的时候,
必须要将泛型定义在方法上。
泛型接口 .
-----------------------------------------------------------
泛型中的通配符: 可以解决当具体类型不确定的时候, 这个通配符就是 ? ; 当操作类型时, 不需要使用类型的
具体功能时, 只使用 Object 类中的功能。 那么可以用 ? 通配符来表未知类型。
泛型限定:
上限: ? extends E: 可以接收 E 类型或者 E 的子类型对象。
下限: ? super E: 可以接收 E 类型或者 E 的父类型对象。
上限什么时候用: 往集合中添加元素时, 既可以添加 E 类型对象, 又可以添加 E 的子类型对象。 为什么? 因为取
的时候, E 类型既可以接收 E 类对象, 又可以接收 E 的子类型对象。
下限什么时候用: 当从集合中获取元素进行操作的时候, 可以用当前元素的类型接收, 也可以用当前元素的父类
型接收。
泛型的细节:
1)、 泛型到底代表什么类型取决于调用者传入的类型, 如果没传, 默认是 Obj ect 类型;
2)、 使用带泛型的类创建对象时, 等式两边指定的泛型必须一致;
原因: 编译器检查对象调用方法时只看变量, 然而程序运行期间调用方法时就要考虑对象具体类型了;
3)、 等式两边可以在任意一边使用泛型, 在另一边不使用( 考虑向后兼容) ;Map 集合:
| --Hashtable: 底层是哈希表数据结构, 是线程同步的。 不可以存储 null 键, null 值。
| --HashMap: 底层是哈希表数据结构, 是线程不同步的。 可以存储 null 键, null 值。 替代了 Hashtable.
| --TreeMap: 底层是二叉树结构, 可以对 map 集合中的键进行指定顺序的排序。
Map 是双列集合。
Map 中的存储的一对元素: 一个是键, 一个是值, 键与值之间有对应(映射) 关系。
特点: 要保证 map 集合中键的唯一性。
1, 添加。
put(key, value) : 当存储的键相同时, 新的值会替换老的值, 并将老值返回。 如果键没有重复, 返回 null;
void putAll(Map) ;
2, 删除。
void clear() : 清空
value remove(key) : 删除指定键。
3, 判断。
boolean isEmpty() :
boolean containsKey(key) : 是否包含 key
boolean containsValue(value) : 是否包含 value
4, 取出。
int size() : 返回长度
value get(key) : 通过指定键获取对应的值。 如果返回 null, 可以判断该键不存在。 当然有特殊情况, 就
是在 hashmap 集合中, 是可以存储 null 键 null 值的。
Collection values() : 获取 map 集合中的所有的值。
5, 想要获取 map 中的所有元素:
原理: map 中是没有迭代器的, collection 具备迭代器, 只 要将 map 集合转成 Set 集合, 可以使用迭代器了 。
之所以转成 set, 是因为 map 集合具备着键的唯一性, 其实 set 集合就来自 于 map, set 集合底层其实用的就是
map 的方法。
★ 把 map 集合转成 set 的方法:
Set keySet() ;
Set entrySet() ; //取的是键和值的映射关系。
---------------------------------------------------------
取出 map 集合中所有元素的方式一: keySet() 方法,可以将 map 集合中的键都取出存放到 set 集合中。 对 set 集合进行迭代。 迭代完成, 再通过 get 方法对获取
到的键进行值的获取- package day15;
- import java.util.*;
- public class mapDemo1 {
- public static void main(String[] args) {
- Map<String,String> hm=new HashMap<String,String>();//创建Map集合
- hm.put("01", "a");//添加元素
- hm.put("04", "d");
- hm.put("02", "b");
- hm.put("03", "c");
- Set<String> keySet=hm.keySet();//把键值提取出来存入set集合
- Iterator<String> it=keySet.iterator();//遍历set集合
- while(it.hasNext())
- {
- String key=it.next();
- System.out.println(key);
- String value=hm.get(key);//根据键进行值的获取
- System.out.println("key:"+key+"value:"+value);
- }
- }
复制代码 取出 map 集合中所有元素的方式二: entrySet()
- package day15;
- import java.util.*;
- import java.util.Iterator;
- import java.util.Map;
- import java.util.Map.Entry;
- public class mapDemo1 {
- public static void main(String[] args) {
- Map<String,String> hm=new HashMap<String,String>();
- hm.put("01", "a");
- hm.put("04", "d");
- hm.put("02", "b");
- hm.put("03","c");
-
- Set<Map.Entry<String,String>> sm=hm.entrySet();//把Map集合中的映射关系取出放到set集合中
- Iterator<Map.Entry<String, String>> it=sm.iterator();
- while(it.hasNext())
- {
- Map.Entry<String,String> me=it.next();
- System.out.println(me.getKey());
- System.out.println(me.getValue());
-
- }
- }
- }
复制代码
使用集合的技巧:
看到 Array 就是数组结构, 有角标, 查询速度很快。
看到 link 就是链表结构: 增删速度快, 而且有特有方法。 addFirst; addLast; removeFirst() ; removeLast() ;
getFirst() ; getLast() ;
看到 hash 就是哈希表, 就要想要哈希值, 就要想到唯一性, 就要想到存入到该结构的中 的元素必须覆盖
hashCode, equals 方法。
看到 tree 就是二叉树, 就要想到排序, 就想要用到比较。
比较的两种方式:
一个是 Comparable: 覆盖 compareTo 方法;
一个是 Comparator: 覆盖 compare 方法。
LinkedHashSet, LinkedHashMap: 这两个集合可以保证哈希表有存入顺序和取出顺序一致, 保证哈希表有序。
集
合什么时候用?
当存储的是一个元素时, 就用 Collection。 当存储对象之间存在着映射关系时, 就使用 Map 集合。
保证唯一, 就用 Set。 不保证唯一, 就用 List
下面做一个练习:
- package day15;
- import java.util.*;
- /*练习“sdfgzxcvasdfxcvdf‘获取该字符串中字母出现的次数
- * 希望打印结果:a(1)c(2)
- * 通过结果发现,每一个字母都有对应的次数,说;明字母和次数之间有映射关系
- * 什么时候使用映射集合呢?当数据之间存在这种映射关系时要先想到map集合
- * 思路:
- * 1,将字符串转换成字符数组,因为要对每一个字母进行操作
- * 2,定义一个map集合,因为打印的字母有顺序所以用treemap
- * 3,遍历字符数组
- * 以每一个字母作为键值查map集合,若返回null则将该字母和1存入集合
- * 如果返回不是null,说明该字母在集合中已经存在并且有对应的次数那么
- * 就获取对应的次数并且进行自增,将该字母和自增后的次数存入集合中会覆盖
- * 之前的次数,*/
- public class mapdemo3 {
- public static void main(String[] args)
- {
- String s="sdfgzxcvasdfxcvdf";
- String s2=printResult(s);//调用打印结果的方法获取一个字符串
- System.out.println(s2);
- }
-
- public static String printResult(String s)
- {
- char[] c=s.toCharArray();//把字符串转换为字符数组
- TreeMap<Character,Integer> tm=new TreeMap<Character,Integer>();//创建Map集合
- for(Character i:c)//遍历数组
- {
- if(!(i<='z'&&i>='a'||i<='Z'&&i>='A'))
- continue;//如果不是字母就进行下一次循环
- Integer in=tm.get(i);
- if(in==null)
- {tm.put(c[i], 1);}
- if(in!=null)
- {in++;
- tm.put(c[i], in);
- }
-
- }
- System.out.println(tm);//打印键值对集合
- Set<Map.Entry<Character,Integer>> sm=tm.entrySet();//提取映射关系存入集合
- Iterator<Map.Entry<Character,Integer>> it=sm.iterator();//遍历集合
- StringBuffer sb=new StringBuffer();//定义字符串缓冲区
- while(it.hasNext())
- {
- Map.Entry<Character,Integer> me=it.next();
- Character key=me.getKey();
- Integer value=me.getValue();
- sb.append(key+"("+value+")");//把键值按照题目上的方式添加到字符串缓冲区
-
- }
- return sb.toString();//返回字符串
- }
- }
复制代码
|
|