泛型,Map集合(非常重要)

泛型:
jdk1.5出现的安全机制。

好处:
1,将运行时期的问题ClassCastException转到了编译时期。
2,避免了强制转换的麻烦。

<>:什么时候用?当操作的引用数据类型不确定的时候。就使用<>。将要操作的引用数据类型传入即可.
   其实<>就是一个用于接收具体引用数据类型的参数范围。
   
在程序中,只要用到了带有<>的类或者接口,就要明确传入的具体引用数据类型 。


泛型技术是给编译器使用的技术,用于编译时期。确保了类型的安全。


运行时,会将泛型去掉,生成的class文件中是不带泛型的,这个称为泛型的擦除。
为什么擦除呢?因为为了兼容运行的类加载器。


泛型的补偿:在运行时,通过获取元素的类型进行转换动作。不用使用者在强制转换了。


泛型类:

/*
public class Tool {


private Object object;


public Object getObject() {
return object;
}


public void setObject(Object object) {
this.object = object;
}

}
*/
//在jdk1.5后,使用泛型来接收类中要操作的引用数据类型。
//泛型类。什么时候用?当类中的操作的引用数据类型不确定的时候,就使用泛型来表示。 




public class Tool<QQ>{
private QQ q;


public QQ getObject() {
return q;
}


public void setObject(QQ object) {
this.q = object;
}


/**
* 将泛型定义在方法上。
* @param str
*/
public <W> void show(W str){
System.out.println("show : "+str.toString());
}
public void print(QQ str){
System.out.println("print : "+str);
}

/**
* 当方法静态时,不能访问类上定义的泛型。如果静态方法使用泛型,
* 只能将泛型定义在方法上。 
* @param obj
*/


// public static <Y> void method( QQ obj)这样不行 不能访问类上定义的QQ类型。
public static <Y> void method(Y obj){   //泛型一定要放在修饰符的后面返回值的前面,这个是自定义Y
System.out.println("method:"+obj);
}
}


print不能打印Integer,因为print的泛型跟着对象走的,而

public <W> void show(W str){
System.out.println("show : "+str.toString());

}这个泛型是在方法上自定义的。


泛型接口:



泛型接口的实现时候还是不确定具体类型,还是用泛型定义,而到创建对象时候才知道,这是两种定义方式(一个是先知道了定义的类型)。



泛型的通配符:? 未知类型。 


这样<T>是可以将定义的类型进行操作,而对于?只仅在不明确类型,并不对这个类型进行操作。





泛型的限定:
? extends E: 接收E类型或者E的子类型对象。上限
一般存储对象的时候用。比如 添加元素 addAll.


? super E: 接收E类型或者E的父类型对象。 下限。
一般取出对象的时候用。比如比较器。
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;


import cn.itcast.p2.bean.Person;
import cn.itcast.p2.bean.Student;
import cn.itcast.p2.bean.Worker;


public class GenericAdvanceDemo2 {


/**
* @param args
*/
public static void main(String[] args) {


ArrayList<Person> al = new ArrayList<Person>();

al.add(new Person("abc",30));
al.add(new Person("abc4",34));

ArrayList<Student> al2 = new ArrayList<Student>();

al2.add(new Student("stu1",11));
al2.add(new Student("stu2",22));
ArrayList<String> al3 = new ArrayList<String>();

al3.add("stu3331");
al3.add("stu33332");

printCollection(al2);
printCollection(al);
}


/**
* 迭代并打印集合中元素。

* 可以对类型进行限定:
* ? extends E:接收E类型或者E的子类型对象。上限!

* ? super E :接收E类型或者E的父类型。下限!
* @param al
*/
/*public static void printCollection(Collection<? extends Person> al) {//Collection<Dog> al = new ArrayList<Dog>()
Iterator<? extends Person> it = al.iterator();

while(it.hasNext()){
// T str = it.next();
// System.out.println(str);
// System.out.println(it.next().toString());
Person p = it.next();

System.out.println(p.getName()+":"+p.getAge());
}

}*/

public static void printCollection(Collection<? super Student> al){
Iterator<? super Student> it = al.iterator();

while(it.hasNext()){

System.out.println(it.next());
}
}


}




上限:

import java.util.ArrayList;


import cn.itcast.p2.bean.Person;
import cn.itcast.p2.bean.Student;
import cn.itcast.p2.bean.Worker;


public class GenericAdvanceDemo3 {


/**
* @param args
*/
public static void main(String[] args) {


ArrayList<Person> al1 = new ArrayList<Person>();

al1.add(new Person("abc",30));
al1.add(new Person("abc4",34));

ArrayList<Student> al2 = new ArrayList<Student>();

al2.add(new Student("stu1",11));
al2.add(new Student("stu2",22));


ArrayList<Worker> al3 = new ArrayList<Worker>();

al3.add(new Worker("stu1",11));
al3.add(new Worker("stu2",22));

ArrayList<String> al4 = new ArrayList<String>();
al4.add("abcdeef");
// al1.addAll(al4);//错误,类型不匹配。

al1.addAll(al2);
al1.addAll(al3);

System.out.println(al1.size());


// printCollection(al2);
// printCollection(al);
}

}


/*
 * 一般在存储元素的时候都是用上限,因为这样取出都是按照上限类型来运算的。不会出现类型安全隐患。 
 * 
 */


class MyCollection<E>{
public void add(E e){

}
public void addAll(MyCollection<? extends E> e){

}
}

下限:

import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;


import cn.itcast.p2.bean.Person;
import cn.itcast.p2.bean.Student;
import cn.itcast.p2.bean.Worker;


public class GenericAdvanceDemo4 {


/**
* @param args
*/
public static void main(String[] args) {


TreeSet<Person> al1 = new TreeSet<Person>(new CompByName());

al1.add(new Person("abc4",34));
al1.add(new Person("abc1",30));
al1.add(new Person("abc2",38));

TreeSet<Student> al2 = new TreeSet<Student>(new CompByName());

al2.add(new Student("stu1",11));
al2.add(new Student("stu7",20));
al2.add(new Student("stu2",22));


TreeSet<Worker> al3 = new TreeSet<Worker>();

al3.add(new Worker("stu1",11));
al3.add(new Worker("stu2",22));

TreeSet<String> al4 = new TreeSet<String>();
al4.add("abcdeef");
// al1.addAll(al4);//错误,类型不匹配。

// al1.addAll(al2);
// al1.addAll(al3);

// System.out.println(al1.size());



Iterator<Student> it = al2.iterator();
while(it.hasNext()){
System.out.println(it.next());
}

}
}




/*
 * class TreeSet<Worker>
 * {
 * Tree(Comparator<? super Worker> comp);
 * }
 * 
 * 什么时候用下限呢?通常对集合中的元素进行取出操作时,可以是用下限。
 * 
 */


class CompByName implements Comparator<Person>{


@Override
public int compare(Person o1, Person o2) {

int temp = o1.getName().compareTo(o2.getName());

return temp==0? o1.getAge()-o2.getAge():temp;
}

}


class CompByStuName implements Comparator<Student>{


@Override
public int compare(Student o1, Student o2) {

int temp = o1.getName().compareTo(o2.getName());

return temp==0? o1.getAge()-o2.getAge():temp;
}

}

用通配符:

import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;


import cn.itcast.p2.bean.Person;
import cn.itcast.p2.bean.Student;
import cn.itcast.p2.bean.Worker;


public class GenericAdvanceDemo5 {


/**
* @param args
*/
public static void main(String[] args) {


ArrayList<Person> al1 = new ArrayList<Person>();

al1.add(new Person("abc",30));
al1.add(new Person("abc4",34));
ArrayList<Person> al2 = new ArrayList<Person>();

al2.add(new Person("abc22222",30));
al2.add(new Person("abc42222222",34));


ArrayList<String> al4 = new ArrayList<String>();
al4.add("abcdeef");
al4.add("abc");

al1.containsAll(al4);


// "abc".equals(new Person("ahahah",20));




}
public static void printCollection(Collection<?> al){//是object的全用?,这里的contains 和 remove都是obj的方法,都是用的equals,比较的地址,obj可以比较任意的对象。
Iterator<?> it = al.iterator();

while(it.hasNext()){

System.out.println(it.next().toString());
}
}
}


class MyCollection2<E>{
public boolean containsAll(Collection<?> coll){


return true;
}
}

集合的一些技巧:

需要唯一吗?
需要:Set
需要制定顺序: 
需要: TreeSet
不需要:HashSet
但是想要一个和存储一致的顺序(有序):LinkedHashSet
不需要:List
需要频繁增删吗?
需要:LinkedList
不需要:ArrayList

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

看名字!

List
|--ArrayList
|--LinkedList


Set
|--HashSet
|--TreeSet


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


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


看到array:就要想到数组,就要想到查询快,有角标.
看到link:就要想到链表,就要想到增删快,就要想要 add get remove+frist last的方法 
看到hash:就要想到哈希表,就要想到唯一性,就要想到元素需要覆盖hashcode方法和equals方法。 
看到tree:就要想到二叉树,就要想要排序,就要想到两个接口Comparable,Comparator 。


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








map集合元素的导出:

import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;


public class MapDemo {


public static void main(String[] args) {

Map<Integer,String> map = new HashMap<Integer,String>();
method_2(map);
}

public static void method_2(Map<Integer,String> map){

map.put(8,"zhaoliu");
map.put(2,"zhaoliu");
map.put(7,"xiaoqiang");
map.put(6,"wangcai");

map的方法:values,返回值是集合。
Collection<String> values = map.values();

Iterator<String> it2 = values.iterator();
while(it2.hasNext()){
System.out.println(it2.next());
}


entryset方法:
/*
* 通过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);

}

图解:




map的Keyset方法。  
//取出map中的所有元素。
//原理,通过keySet方法获取map中所有的键所在的Set集合,在通过Set的迭代器获取到每一个键,
//在对每一个键通过map集合的get方法获取其对应的值即可。
/*
Set<Integer> keySet = map.keySet();
Iterator<Integer> it = keySet.iterator();

while(it.hasNext()){
Integer key = it.next();
String value = map.get(key);
System.out.println(key+":"+value);

}
*/

}

public static void method(Map<Integer,String> map){//学号和姓名


// 添加元素。
System.out.println(map.put(8, "wangcai"));//null
System.out.println(map.put(8, "xiaoqiang"));//wangcai 存相同键,值会覆盖。
map.put(2,"zhangsan");
map.put(7,"zhaoliu");


//删除。
// System.out.println("remove:"+map.remove(2));

//判断。
// System.out.println("containskey:"+map.containsKey(7));

//获取。 
System.out.println("get:"+map.get(6));


System.out.println(map);

Outer.Inner.show();
}

}


interface MyMap{
public static interface MyEntry{//内部接口
void get();
}
}


class MyDemo implements MyMap.MyEntry{
public void get(){}
}


class Outer{
static class Inner{
static void show(){}
}
}

===========================================================


集合的一些技巧:


需要唯一吗?
需要:Set
需要制定顺序: 
需要: TreeSet
不需要:HashSet
但是想要一个和存储一致的顺序(有序):LinkedHashSet
不需要:List
需要频繁增删吗?
需要:LinkedList
不需要:ArrayList

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


看名字!




List
|--ArrayList
|--LinkedList


Set
|--HashSet
|--TreeSet


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


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


看到array:就要想到数组,就要想到查询快,有角标.
看到link:就要想到链表,就要想到增删快,就要想要 add get remove+frist last的方法 
看到hash:就要想到哈希表,就要想到唯一性,就要想到元素需要覆盖hashcode方法和equals方法。 
看到tree:就要想到二叉树,就要想要排序,就要想到两个接口Comparable,Comparator 。


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




============================================


Map:一次添加一对元素。Collection 一次添加一个元素。
Map也称为双列集合,Collection集合称为单列集合。
其实map集合中存储的就是键值对。 
map集合中必须保证键的唯一性。 


常用方法:
1,添加。
value put(key,value):返回前一个和key关联的值,如果没有返回null.


2,删除。
void  clear():清空map集合。
value remove(key):根据指定的key翻出这个键值对。 


3,判断。
boolean containsKey(key):
boolean containsValue(value):
boolean isEmpty();


4,获取。 
value get(key):通过键获取值,如果没有该键返回null。
当然可以通过返回null,来判断是否包含指定键。 
int size(): 获取键值对的个数。 



Map常用的子类:
|--Hashtable :内部结构是哈希表,是同步的。不允许null作为键,null作为值。
|--Properties:用来存储键值对型的配置文件的信息,可以和IO技术相结合。
|--HashMap : 内部结构是哈希表,不是同步的。允许null作为键,null作为值。

|--TreeMap : 内部结构是二叉树,不是同步的。可以对Map集合中的键进行排序。 




hashmap:

import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;


import cn.itcast.p2.bean.Student;


public class HashMapDemo {


/**
* @param args
*/
public static void main(String[] args) {



/*
* 将学生对象和学生的归属地通过键与值存储到map集合中。

*/

HashMap<Student,String> hm = new HashMap<Student,String>();



hm.put(new Student("lisi",38),"北京");
hm.put(new Student("zhaoliu",24),"上海");
hm.put(new Student("xiaoqiang",31),"沈阳");
hm.put(new Student("wangcai",28),"大连");
hm.put(new Student("zhaoliu",24),"铁岭");

// Set<Student> keySet = hm.keySet();
// Iterator<Student> it = keySet.iterator();

Iterator<Student> it = hm.keySet().iterator();

while(it.hasNext()){
Student key = it.next();
String value = hm.get(key);
System.out.println(key.getName()+":"+key.getAge()+"---"+value);
}


}


}


treemap:

import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;


import cn.itcast.p2.bean.Student;
import cn.itcast.p3.comparator.ComparatorByName;


public class TreeMapDemo {


/**
* @param args
*/
public static void main(String[] args) {


TreeMap<Student,String> tm = new TreeMap<Student,String>(new ComparatorByName());

tm.put(new Student("lisi",38),"北京");
tm.put(new Student("zhaoliu",24),"上海");
tm.put(new Student("xiaoqiang",31),"沈阳");
tm.put(new Student("wangcai",28),"大连");
tm.put(new Student("zhaoliu",24),"铁岭");


Iterator<Map.Entry<Student, String>> it = tm.entrySet().iterator();

while(it.hasNext()){
Map.Entry<Student,String> me = it.next();
Student key = me.getKey();
String value = me.getValue();

System.out.println(key.getName()+":"+key.getAge()+"---"+value);
}

}


}


Map的练习:

import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;




/*
 * 练习:
 * "fdgavcbsacdfs" 获取该字符串中,每一个字母出现的次数。
 * 要求打印结果是:a(2)b(1)...;
 * 思路:
 * 对于结果的分析发现,字母和次数之间存在着映射的关系。而且这种关系很多。
 * 很多就需要存储,能存储映射关系的容器有数组和Map集合。
 * 关系一方式有序编号吗?没有!
 * 那就是使用Map集合。 又发现可以保证唯一性的一方具备着顺序如 a b c ...
 * 所以可以使用TreeMap集合。
 * 
 * 这个集合最终应该存储的是字母和次数的对应关系。 
 * 
 * 1,因为操作的是字符串中的字母,所以先将字符串变成字符数组。
 * 2,遍历字符数组,用每一个字母作为键去查Map集合这个表。
 * 如果该字母键不存在,就将该字母作为键 1作为值存储到map集合中。
 * 如果该字母键存在,就将该字母键对应值取出并+1,在将该字母和+1后的值存储到map集合中,
 * 键相同值会覆盖。这样就记录住了该字母的次数.
 * 3,遍历结束,map集合就记录所有字母的出现的次数。oy.
 * 
 * 
 */


public class MapTest {


/**
* @param args
*/
public static void main(String[] args) {



String str = "fdg+avAdc  bs5dDa9c-dfs";

String s = getCharCount(str);

System.out.println(s);

}


public static String getCharCount(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'))
// if(!(Character.toLowerCase(chs[i])>='a' && Character.toLowerCase(chs[i])<='z'))
continue;

//将数组中的字母作为键去查map表。
Integer value = map.get(chs[i]);

int count = 1;

//判断值是否为null.
if(value!=null){
count = value+1;
}
// count++;
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();
}


}








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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值