黑马程序员_集合框架(二)

来源:互联网 发布:java读英文文件乱码 编辑:程序博客网 时间:2024/06/05 21:41

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

七、泛型

泛型概述

泛型是JDK1.5以后出现的新特性,用于解决安全问题,是一个安全机制


泛型的好处

1、将运行时期的问题ClassCastException问题转换成了编译失败,体现在编译时期,程序员就可以解决问题

2、避免了强制转换的麻烦


泛型的格式

通过< >来定义操作的引用类型,当使用集合时,将集合中要存储的数据类型作为参数传递到<>里。


在使用java提供的对象时什么时候使用泛型呢

通常在集合框架中很常见,只要见到<>就写泛型


什么时候定义泛型

当类中要操作的引用数据类型不确定的时候

当操作数据类型不确定的时候,可以将泛型定义在类上

public <W> void method(W w){    System.out.println("method:"+w);}

静态方法上的泛型

静态方法上的泛型:静态方法无法访问类上定义的泛型。如果静态方法数据类型不确定的时候必须要将泛型定义在方法上。

public static <Q> void function(Q t) {    System.out.println("function:"+t);}

泛型接口

interface Inter<T> {    void show<T t>;}class InterImpl<R> implements Inter<R>{    public void show(R r)    {        System.out.println("show:"+r);    }}

泛型通配符

可以解决当具体类型不确定的时候,这个通配符就是?;当操作类型时,不需要使用类型的具体功能时,只使用Object类中的功能。那么可以用?通配符来表示未知类型。

也可以理解为占位符


泛型限定

上限:?extends E:可以接收E类型或者E的子类型对象

下限:? super E:可以接收E类型或者E的父类型对象

局限性:不可以引用数据类型的特有方法


泛型的细节

1、泛型到底是什么类型取决于调用者传入的类型,如果没传,默认是Object类型

2、使用泛型创建对象时,等式两边指定的泛型必须一致

原因:编译器检查对象调用方法时只看变量,然而程序运行期间调用方法时就要考虑对象具体类型了;

3、等式两边可以在任意一边使用泛型,在另一边不使用。(考虑向后兼容)


示例:

import java.util.*;class  GenericDemo{public static void main(String[] args) {ArrayList<Person> al = new ArrayList<Person>();al.add(new Person("abc1"));al.add(new Person("abc2"));al.add(new Person("abc3"));ArrayList<Student> al1 = new ArrayList<Student>();al1.add(new Student("abc--1"));al1.add(new Student("abc--2"));al1.add(new Student("abc--3"));printColl(al1);  }//定义一个上限的泛型方法public static void printColl(Collection<? extends Person> al){Iterator<? extends Person> it = al.iterator();while(it.hasNext()){System.out.println(it.next().getName());}}}class Person//定义父类{private String name;Person(String name){this.name = name;}public String getName(){return name;}}class Student extends Person//子类学生继承父类{Student(String name){super(name);}}

八、Map集合

概述

Map集合容器存储的是键Key和Value值的对应关系,即存储键值对。而且要保证键Key的唯一性。


|--Hashtable:底层是哈希表数据结构,是线程同步的。不可以储存null键,null值。

|--HashMap:底层是哈希表数据结构,是线程不同步的。可以存储null键,null值。替代了Hashtable。

|--TreeMap:底层是二叉树结构,可以对map集合中的键进行指定顺序的排序。


Map和Collection的区别

Map一次添加一对元素,Collection一次添加一个元素。Map也称为双列集合,Collection集合称为单列集合。

Map中存储的键和值是对应关系(映射)关系。

特点:要保证map集合中键的唯一性。


方法

1、添加

put(key,value);//当存储的键相同时新的值会替换老的值,并将老的值返回。如果键没有重复返回null.

void putAll(Map);

2、删除

void clear();清空

value remove(key);删除指定键

3、判断

boolean isEmpty();

boolean containsKey(key);是否包含value

boolean containsValue(value):是否包含value

4、取出

int size();返回长度

value get(key);通过指定键获取对应的值。如果返回null,可以判断该键不存在。当然有特殊情况,就是在hashmap集合中,是可以存储null键null值的。

Collection values();获取map集合中所有的值。


如何获取map中所有的元素

map中没有迭代器,Collection具备迭代器,只要将map集合转成Set集合,就可以使用迭代器了

之所以转成Set,是因为map集合具备着键的唯一性,其实set集合来自于map,set集合底层其实使用的就是map方法


Map集合的两种取出方式

keySet:将Map中所有的键存入到Set集合,因为Set具备迭代器。所以可以通过迭代方式取出所有的键,在根据get方法,获取每一个键对应的值。

Set entrySet:将map集合中的映射关系存入到了Set集合中,而这个关系的数据类型是:Map.Entry。(其实Entry也是一个接口,它是Map接口中的一个内部接口)


取出map集合中所有元素的方式

keySet方法

Set keySet = map.keySet();//取出map集合中所有的键Iterator it = keySet.iterator();//对set集合进行迭代while(it.hasNext()) {Object key = it.next();Object value = map.get(key);//通过get方法对获取键进行值的获取System.out.println(key+":"+value);}

entrySet方法

Set entrySet = map.entrySet();//将map映射关系取出存到集合Iterator it = entrySet.iterator();while(it.hasNext()) {Map.Entry  me = (Map.Entry)it.next();System.out.println(me.getKey()+"::::"+me.getValue());//通过getKey和getValue分别获得键和值}

map方式取出元素练习

代码如下

/*需求1.描述一个学生2.定义map容器,将学生作为键,地址作为值,存入。3.获取map集合中的元素。*/import java.util.*;class MapTest {public static void main(String[] args) {HashMap<Student,String> hm=new HashMap<Student,String>();//Map集合添加元素方法是put,而不是addhm.put(new Student("lisi01",21),"beijing");hm.put(new Student("lisi03",23),"guangdong");hm.put(new Student("lisi02",22),"shanghai");//keySet取出方式,先取键Set<Student> keySet=hm.keySet();Iterator<Student> it=keySet.iterator();//对Set集合进行迭代while(it.hasNext()){Student stu=it.next();String addr=hm.get(stu);//通过get方法对获取的键进行值的获取System.out.println("Student:"+stu+"...addr:"+addr);}//entrySet取出方式,取出映射关系Set<Map.Entry<Student,String>> entrySet=hm.entrySet();Iterator<Map.Entry<Student,String>> it2=entrySet.iterator();while(it2.hasNext()) {Map.Entry<Student,String> me=it2.next();Student stu=me.getKey();String addr=me.getValue();System.out.println("Student:"+stu+"_ _ _addr:"+addr);}}}class Student {private String name;private int age; Student(String name,int age) {this.name=name;this.age=age;}public String getName() {return name;}public int getAge() {return age;}public String toString() {return name+":"+age;}//自定义对象需要覆写hashCode方法和equals方法public int hashCode() {return name.hashCode()+age*39;}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;}}


练习

"ak+abAf1c,dCkaAbc-defa"获取该字符串中的字母出现的次数。

希望打印结果:a(1)c(2).....

import java.util.*;class  MapTest {public static void main(String[] args) {String s= charCount("ak+abAf1c,dCkaAbc-defa");System.out.println(s);}public static String charCount(String str) {char[] chs = str.toCharArray();TreeMap<Character,Integer> tm = new TreeMap<Character,Integer>();int count = 0;for(int x=0; x<chs.length; x++) {//每一个字母作为键查map集合if(!(chs[x]>='a' && chs[x]<='z' || chs[x]>='A' && chs[x]<='Z'))//排除不是字母的元素//不是字母继续循环continue;Integer value = tm.get(chs[x]);//通过get方法获取键所对应的值if(value!=null)count = value;count++;tm.put(chs[x],count);//put直接往集合中存储字符和数字,为什么可以,因为自动装箱。count = 0;}  StringBuilder sb = new StringBuilder();//将映射关系储存到set集合Set<Map.Entry<Character,Integer>> entrySet = tm.entrySet();//获取set集合的迭代器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();}}























0 0
原创粉丝点击