首页 > 代码库 > java(八)集合

java(八)集合

Map

Map<K,V>:Map集合一次添加一对元素,Collection一次添加一个元素。

          所以Map集合也称为双列集合,而Collection称为单列集合。

 其实Map集合存储的就是键值对。

   Map集合必须保证键的唯一性。

常用方法:1.添加:

value put(key,value):返回前一个和key关联的值,若没有则返回null。

 2.删除:

void clear():清空map集合。

value remove():根据指定的key删除这个键值对。

 3.判断

boolean containsKey(key);

boolean containsValue(Value);

boolean isEmpty();

 4.获取

value get(Key):通过键获取值,若没有该键返回null。

      也可以通过返回null来判断是否包含指定键。

int size();获取键值对个数。

常用方法演示:

package day18;

import java.util.HashMap;

import java.util.Map;


public class MapDemo {


public static void main(String[] args) {

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

method(map);

}

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(map);     //输出是无序的。

//删除元素

System.out.println("remove:"+map.remove(2));

System.out.println(map);

//判断

System.out.println("containsKey:"+map.containsKey(7));

//获取

System.out.println("get:"+map.get(6));

System.out.println(map);

}

}

输出结果为:

wangcai

{2=zhangsan, 7=zhaoliu, 8=xiaoqiang}

remove:zhangsan

{7=zhaoliu, 8=xiaoqiang}

containsKey:true

get:null

{7=zhaoliu, 8=xiaoqiang}


get方法一次只能取出一个元素,怎么能全部取出呢?(3种方法)

1.取出map中的所有元素原理:先通过KeySet方法获取map中所有的键所在的Set集合,

再通过Set的迭代器获取到每一个键,再对每一个键通过map的get方法获取其对应的值即可。


2.通过map转换成set就可以迭代,那么就找到了另一个方法entrySet。

该方法将键和值的映射关系作为作为对象存储到了Set集合中,而这个映射关系的类型就是Map.Entry类型(结婚证)


3.如果只获取所有的value值,不需要获取键值,有一种简便的方法——values方法。


package day18;

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();

method_KeySet(map);

method_entrySet(map);

method_values(map);

}

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

map.put(8, "wangcai");

map.put(2, "zhangsan");

map.put(7, "zhaoliu");

map.put(6, "yaoming");

Set<Integer> KeySet=map.keySet();

Iterator <Integer> it=KeySet.iterator();

while(it.hasNext()){

Integer key=it.next();

String value=http://www.mamicode.com/map.get(key);

System.out.println(key+":"+value);

}

}

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

map.put(8, "wangcai");

map.put(2, "zhangsan");

map.put(7, "zhaoliu");

map.put(6, "yaoming");

Set<Map.Entry<Integer,String>> entrySet=map.entrySet();

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

//Entry是Map接口中的内部接口,所以定义迭代器时要这么写,参考内部类。

while(it.hasNext()){

Map.Entry<Integer,String> me=it.next();

Integer key=me.getKey();

String value=http://www.mamicode.com/me.getValue();

System.out.println(key+":"+value);

}

}

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

map.put(8, "wangcai");

map.put(2, "zhangsan");

map.put(7, "zhaoliu");

map.put(6, "yaoming");

Collection<String> values=map.values();

Iterator<String> it=values.iterator();

while(it.hasNext()){

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

}

}



Map常用的子类:

HashTable:内部结构是哈希表,是同步的。不支持null作为键和null作为值。

   properties:HashTable的一个子类对象,用来存储键值类型的配置文件的信息,可以和IO技术相结合,所以相当牛逼。

HashMap:内部结构是哈希表,不是同步的。支持null作为键和null作为值。

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


HashMapDemo演示:

package day18;

import java.util.HashMap;

import java.util.Iterator;

import java.util.Set;


import Class.Student;


public class HashMapDemo {


/**

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

*/

public static void main(String[] args) {

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

hm.put(new Student("lisi",18),"北京");

hm.put(new Student("zhangsan",19),"西安");

hm.put(new Student("wangwu",28),"深圳");

hm.put(new Student("xiaoqiang",24),"铁岭");

hm.put(new Student("xiaoqiang",24),"上海");//注意这里要重写HashCode和equals,

                                  //要不然这个对象和上面对象的键相同,上海就会被铁岭覆盖。

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=http://www.mamicode.com/hm.get(key);

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

}

}

}

输出结果为:

wangwu:28---深圳

lisi:18---北京

zhangsan:19---西安

xiaoqiang:24---上海

xiaoqiang:24---铁岭



TreeMapDemo演示:

package day18;

import java.util.Iterator;

import java.util.Map;

import java.util.Set;

import java.util.TreeMap;


import Class.Student;

import Comparator.ComparatorByName;


public class TreeMapDemo {


public static void main(String[] args) {

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

tm.put(new Student("lisi",18),"北京");

tm.put(new Student("zhangsan",19),"西安");

tm.put(new Student("wangwu",28),"深圳");

tm.put(new Student("xiaoqiang",24),"铁岭");

tm.put(new Student("xiaoqiang",24),"上海");//注意这里要重写HashCode和equals,

                                  //要不然这个对象和上面对象的键相同,上海就会被铁岭覆盖。


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=http://www.mamicode.com/me.getValue();

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

}

}

}

输出结果为:(TreeMap不能重复)

lisi:18---北京

wangwu:28---深圳

xiaoqiang:24---上海

zhangsan:19---西安





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

好处:

1.将运行时起的问题ClassCastException转到了编译时期。

2.避免了强制转换的麻烦。

什么时候用<>?

当操作的引用数据类型不确定时就使用<>,将要操作的引用数据类型传入即可。

其实<>就是一个用于接收具体引用数据类型的参数范围。

在程序中,只要用到了带有<>的类或者接口,就要明确传入的具体引用数据类型。


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

运行时,会将泛型去掉,生成的class文件中是不带泛型的,这称为泛型的擦除。

为什么要擦除呢?这是为了兼容运行的类加载器。

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


在jdk1.5后,使用泛型类来接收类中要操作的引用数据类型。

这就是泛型类。什么时候用?当类中操作的引用数据类型不确定时,就要用泛型表示。

静态方法不能访问类上定义的泛型,如果静态方法只用到了泛型,只能定义在方法上

泛型接口:将泛型定义在接口上。



LinkedHashMap:和HashMap一个用法,只不过这是有序的,这里的有序是指咋存进去,咋取出来。

Map集合在有映射关系时,可以优先考虑。在查表法中的应用较为多见。

package day18;

import java.util.Iterator;

import java.util.Map;

import java.util.TreeMap;


public class MapTest {


/**

* 练习:"fdg avcb+sac/*dfSs"获取该字符串中,每一个字母出现的字数。

* 要求打印结果是a(2)b(0)....

* 思路:

* 对于结果的分析发现,字母和次数之间存在着映射关系,而且很多。

* 这就需要存储了,能存储映射关系的容器有数组和map集合。

* 关系的一方是有序编号吗?没有,所以就要用map集合了。

* 又发现可以保证唯一性的一方具备着顺序如a b c...  所以就用TreeMap集合了。

* 这个集合中最终应该存储的是字母和次数的对应关系。

* 1.因为操作的是字符串中的字母,所以先将字符串变成字符数组。

* 2.遍历字符数组,用每一个字母作为键值,去查map集合这个表。

*   如果该字母不存在,就将该字母作为键存储到map集合中。

*   如果该字母存在,就将该字母键对应值取出并+1,再将该字母键和+1后的值存储到map集合中。

*   键相同值会覆盖,这样就记录住了该子母出现的次数。

* 3.遍历结束,map集合记录了所有字母以及出现的次数。

*/

public static void main(String[] args) {

String str="fdgavcbsacdfss";

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‘))

continue;

//将数组中的字母作为键去查map表。这里用ContainsKey比较麻烦,直接用get,为空就说明没有这个字母

int count=1;

Integer value=http://www.mamicode.com/map.get(chs[i]);

/*这几句比较符合逻辑,容易理解,但通常不这么写。

if(value=http://www.mamicode.com/=null)

map.put(chs[i], 1);

else

map.put(chs[i], value+1);

*/

if(value!=null){

count=value+1;

}

map.put(chs[i], count);

}

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=http://www.mamicode.com/map.get(key);

sb.append(key+"("+value+")");

}

return sb.toString();

}

}












Utilities(工具)

Collections:(注意不带S的是接口,带S的是工具类)

    集合框架的工具类,里面的方法都是静态的。

Arrays:集合框架的工具类,方法也都是静态的。


Collections演示:

package day18;


import java.util.ArrayList;

import java.util.Collections;

import java.util.List;

import java.util.TreeSet;


import Comparator.ComparatorByLength;

//Collections是集合框架的工具类,里面的方法都是静态的。

public class ToolCollectionsDemo {


public static void main(String[] args) {

demo_1();

demo_2();

demo_3();

demo_4();

demo_5();

}


public static void demo_1(){

List<String> list=new ArrayList<String>();

list.add("kk");

list.add("abcde");

list.add("cba");

list.add("zzz");

list.add("cba");

list.add("nbaa");

System.out.println(list);

//对list集合进行指定顺序的排序。

Collections.sort(list);      //直接调用工具类的Sort方法

System.out.println(list); 

mySort(list);                //自己写的一个排序方法,可以看出最终结果和Sort一样。

Collections.sort(list,new ComparatorByLength());

System.out.println(list);

}

public static <T extends Comparable<? super T>> void mySort(List<T> list){          //加了泛型,而且T必须具备可比较性,提高了程序拓展性

//public static void mySort(List<String> list){       //写这句拓展性不高,只能给String排序

for(int i=0;i<list.size()-1;i++){

for(int j=i+1;j<list.size();j++){

if(list.get(i).compareTo(list.get(j))>0){

T temp=list.get(i);

list.set(i,list.get(j));

list.set(j, temp);

}

}

}

System.out.println(list);

}

public static void demo_2(){               //颠倒顺序的方法

TreeSet<String> ts=new TreeSet<String>(Collections.reverseOrder(new ComparatorByLength()));

ts.add("abc");

ts.add("hahaha");

ts.add("a");

ts.add("nba");

ts.add("mlgb");

System.out.println(ts);

}

public static void demo_3(){

List<String> list=new ArrayList<String>();

list.add("kk");

list.add("abcde");

list.add("cba");

list.add("zzz");

list.add("cba");

list.add("nbaa");

System.out.println(list);

Collections.replaceAll(list,"cba", "nba");       //替换的方法,把cba改成nba  原理就是用indexOf方法加set方法

System.out.println(list);

}

public static void demo_4(){

List<String> list=new ArrayList<String>();

list.add("kk");

list.add("ab");

list.add("cba");

System.out.println(list);

Collections.fill(list, "cc");  //将集合中的所有值全部替换。

System.out.println(list);

}

public static void demo_5(){

List<String> list=new ArrayList<String>();

list.add("xiaoqiang");

list.add("wangcai");

list.add("zhaoliu");

System.out.println(list);

Collections.shuffle(list);  //随机重新排列集合元素的顺序。

System.out.println(list);

}

}

          


           List asList(数组)将数组转成集合。

* 好处:可以使用集合的方法操作数组中 的元素

* 注意:数组长度固定,所以不能使用增和删方法,否则异常

* 如果数组中的元素是对象,那么转成集合时,直接将数组中的元素作为集合中的元素进行集合存储。

* 如果数组中的原始是基本类型数值, 那么会将该数组作为集合中的元素进行存储。


           集合转数组:

* 使用的就是Collection接口中的toArray方法

* 好处:可以对集合中的元素操作的方法进行限定,不允许对其增删

* toArray方法需要传入一个指定类型的数组。

* 如果长度小于集合的size,那么该方法会创建一个同类型并和集合相同size的数组。

* 如果长度大于集合的size,那么该方法就会使用指定的数组,存储集合中的元素,其他位置默认为null。

* 所以建议最好长度指定为集合的size。



foreach语句:

格式:for(类型 变量:Collection集合或数组){

}

例子:List<String> list=new ArrayList<String>

list.add("abc1");

list.add("abc2");

list.add("abc3");

/*原来这么写:、

iterator<String> it=list.iterator();

while(it.hasNext()){

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

}*/

for(String s:list){

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

}  //这个就是用来简化书写的,可以遍历集合,也可以遍历数组

传统for和增强for的区别?

传统for可以完成对语句执行很多次,因为可以控制循环的增量和条件

增强for是一种简化形式,必须有遍历的目标,要么是集合,要么是数组。


对数组的遍历如果仅仅是获取数组中的元素,可以使用高级for。

如果要对数组的角标进行操作,建议使用传统for。

高级for只能遍历单列集合,所以不能直接遍历map,要将map转成set才能用。





函数的可变参数

其实就是一个数组,但是接受的是数组的元素,自动将这些元素封装成数组,简化了书写。

注意:可变参数类型,必须定义在参数列表的结尾处。

public class newAddDemo {


/**

* @param args

*/

public static void main(String[] args) {

int sum=newAdd(1,2,3);

System.out.println(sum);

int sum1=newAdd(1,2,3,4,5);

System.out.println(sum1);

}

//函数的可变参数int ...

//注意可变参数类型必须定义在参数列表的结尾,比如newAdd(int x,int... arr)

public static int newAdd(int... arr) { 

int sum=0;

for (int i = 0; i < arr.length; i++) {

sum+=arr[i];

}

return sum;

}

}
























本文出自 “12946849” 博客,请务必保留此出处http://12956849.blog.51cto.com/12946849/1932020

java(八)集合