Java基础(集合——Map、Collcetions工具类)

来源:互联网 发布:最新手机淘宝开店教程 编辑:程序博客网 时间:2024/05/16 12:41

Map
一、体系
          Map
            |——Hashtable    底层是哈希表数据结构,不可以存入null键或null值,线程是同步的,效率低,JDK1.0(被HashMap替代)
            |——HashMao     底层是哈希表数据结构,可以存入null键或null值,线程是不同步的  效率比较高,JDK1.1
            |——TreeMap     底层是二叉树数据结构,线程是不同步的,可以用于给Maori集合中的键进行排序
二、Maori和collection的不同
1、Map和Collection在集合框架中属于并列存在
2、Map存储的是键值对
3、Map存储元素使用的是put方法,Collection存储元素使用的是add方法
4、Map中没有直接元素的方法,而是先转成Set集合,在使用迭代取出
5、Map中的键是唯一的
6、其实Set底层使用的就是Map集合
三、Map格式
Map<K,V> map = new HashMap<K,V>();
k:代表键的类型,是唯一的,使用put方法添加时,可以添加相同的键,但是后面的键对应的值会覆盖前面键对应的值。
V:  代表值得类型,不是唯一的。
四、Map集合常用方法

1、增加
1、put(K key,V value)    返回值为V  注:使用put添加元素时,如果要添加的元素不存在,则会返回null,如果要添加的元素已经存在,那么新添加的键上的value会覆盖和指定要添加的键相同的value上的值
2、putAll(Map<? extendsK,? extendsV> m)         返回值类型为void   注:用于添加指定集合,添加的集合中的键必须是已有集合键的类型或其子类型,添加的集合中的值必须是又有集合值得类型或其子类型
2、删除
1、clear()          返回值为void    清空集合

2、remove(Object key)  返回值为V    用于删除指定键,并返还指定键上的值

3、获取
1、entrySet()    返回值 Set<Map.Entry<K,V>>   注:该返回值是一个set集合 而返回的set集合中元素的类型必须是Map.Entry<K,V>类型    Map.Entry是一个内部类
2、get(Object key)  返回值为V   用于返回指定键上的value
3、keySet()          返回值为 Set<K>     获取集合中的所有键,方便使用迭代器
4、判断
1、containsKey(Object key)        判断指定的键是否存在
2、containsValue(Object value)    判断指定的值是否存在
3、isEmpty()        返回值为 boolean   用于判断集合是否为空
五、Map集合常用的两种取出方式
1、keySet()
       原理:将Map集合中的所有键取出存入到Set集合中,因为Set集合具备迭代器,所以可以使用keySet取出所有键,然后在使用迭代的方式取出所有的值。
       图例:
             
2、entrySet()
       原理:将Map集合中的映射关系存入到Set集合中,而这个关系的数据类型就是Set<Map.Entry<K,V>>    而,其实Entry它就是一个Map接口中的一个内部接口,而它有俩个方法可以获取元素,getKey()、getValue();
       图例:
              
二、entrySet部分源码:
       
class Map{//这里必须是静态的,应为Map.Entry()是直接调用的public static interface Entry{public abstract Object getKay();public abstract Object getValue();}}class HashMap implements Map{//必须要实现Map中的方法和Entry中方法class Node implements Entry{public Object getKey(){}public Object getValue();}}
三、keySet、entrySet练习
       
/*获取Map中的元素keySet(0entrySet()*/import java.util.*;class  MapDemo{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");/*----------ketSet---------*/Set<String> set = map.keySet();for(Iterator<String> it = set.iterator();it.hasNext();){String key = it.next();      //获取键String value = map.get(key);   //获取值System.out.println(key+"=="+value);}/*---------entrySet----------*/Set<Map.Entry<String,String>> se = map.entrySet();     //这里返回的是映射关系,所以泛型应该是Map.Entry<String,String>for(Iterator <Map.Entry<String,String>> it = se.iterator();it.hasNext();){Map.Entry<String,String> me = it.next();String key = me.getKey();     //获取键String value = me.getValue();   //获取值System.out.println(key+"==================="+value);}}}
四、去除重复对象
       
/*每一个学生都有对应的归属地。学生Student,地址String。学生属性:姓名,年龄。注意:姓名和年龄相同的视为同一个学生。保证学生的唯一性。1,描述学生。2,定义map容器。将学生作为键,地址作为值。存入。3,获取map集合中的元素。*///定义学生类import java.util.*;class Student implements Comparable<Student>{private String name;private int age;public Student(String name,int age){this.name = name;this.age = age;}public String getName(){return name;}public int getAge(){return age;}//因为不确定用户使用的是TreeMap还是HashMap 所以应该复写equals方法、hasCode方法和compareTo方法public boolean equals(Object obj){if(!(obj instanceof Student))throw new ClassCastException("类型不匹配");return this.name.equals(((Student)obj).name)&&this.age==age;}public int hashCode(){return this.name.hashCode()+age*21;}public int compareTo(Student s){int num = this.name.compareTo(s.name);if(num==0)return new Integer(this.age).compareTo(new Integer(s.age));return num;}}class  MapDemo1{public static void main(String[] args) {//HashMap<Student,String> hm = new HashMap<Student,String>();TreeMap<Student,String> hm = new TreeMap<Student,String>();hm.put(new Student("lisi1",21),"beijing");hm.put(new Student("lisi1",21),"tianjin");hm.put(new Student("lisi2",22),"shanghai");hm.put(new Student("lisi3",23),"nanjing");hm.put(new Student("lisi4",24),"wuhan");/*------keySet-----*/for(Iterator<Student> it = hm.keySet().iterator();it.hasNext();){Student stu = it.next();String value = hm.get(stu);System.out.println(stu.getName()+":"+stu.getAge()+"=="+value);}/*--------entrySet--------*/for(Iterator<Map.Entry<Student,String>> it = hm.entrySet().iterator();it.hasNext();){Map.Entry<Student,String> me = it.next();Student stu = me.getKey();System.out.println(stu.getName()+":"+stu.getAge()+"========"+me.getValue());}}}
五、自定义比较器
       
//定义学生类import java.util.*;class Student implements Comparable<Student>{private String name;private int age;public Student(String name,int age){this.name = name;this.age = age;}public String getName(){return name;}public int getAge(){return age;}//因为不确定用户使用的是TreeMap还是HashMap 所以应该复写equals方法、hasCode方法和compareTo方法public boolean equals(Object obj){if(!(obj instanceof Student))throw new ClassCastException("类型不匹配");return this.name.equals(((Student)obj).name)&&this.age==age;}public int hashCode(){return this.name.hashCode()+age*21;}public int compareTo(Student s){int num = this.name.compareTo(s.name);if(num==0)return new Integer(this.age).compareTo(new Integer(s.age));return num;}}//自定义比较器//需求:对学生对象的年龄进行降序排序。class stuAgeComparator implements Comparator<Student>{public int compare(Student stu1,Student stu2){int num = new Integer(stu2.getAge()).compareTo(new Integer(stu1.getAge()));if(num==0)return stu2.getName().compareTo(stu1.getName());return num;}}class  MapDemo1{public static void main(String[] args) {//HashMap<Student,String> hm = new HashMap<Student,String>();TreeMap<Student,String> hm = new TreeMap<Student,String>(new stuAgeComparator());hm.put(new Student("lisi1",21),"beijing");hm.put(new Student("lisi1",21),"tianjin");hm.put(new Student("lisi2",22),"shanghai");hm.put(new Student("lisi3",23),"nanjing");hm.put(new Student("lisi4",24),"wuhan");/*------keySet-----*/for(Iterator<Student> it = hm.keySet().iterator();it.hasNext();){Student stu = it.next();String value = hm.get(stu);System.out.println(stu.getName()+":"+stu.getAge()+"=="+value);}/*--------entrySet--------*/for(Iterator<Map.Entry<Student,String>> it = hm.entrySet().iterator();it.hasNext();){Map.Entry<Student,String> me = it.next();Student stu = me.getKey();System.out.println(stu.getName()+":"+stu.getAge()+"========"+me.getValue());}}}
六、获取字母出现的次数
       
/*练习:"sdfgzxcvasdfxcvdf"获取该字符串中的字母出现的次数。希望打印结果:a(1)c(2).....通过结果发现,每一个字母都有对应的次数。说明字母和次数之间都有映射关系。注意了,当发现有映射关系时,可以选择map集合。因为map集合中存放就是映射关系。什么使用map集合呢?当数据之间存在这映射关系时,就要先想map集合。思路:1,将字符串转换成字符数组。因为要对每一个字母进行操作。2,定义一个map集合,因为打印结果的字母有顺序,所以使用treemap集合。3,遍历字符数组。将每一个字母作为键去查map集合。如果返回null,将该字母和1存入到map集合中。如果返回不是null,说明该字母在map集合已经存在并有对应次数。那么就获取该次数并进行自增。,然后将该字母和自增后的次数存入到map集合中。覆盖调用原理键所对应的值。4,将map集合中的数据变成指定的字符串形式返回。*/import java.util.*;class  MapDemo2{public static void main(String[] args) {String str = getCount("abcdabcdeabffgac");  System.out.println(str.substring(0,str.length()-1));}public static String getCount(String str){//将字符串转换成字符数组char [] ch = str.toCharArray();//定义集合存储每个字符以及出现的次数Map<Character,Integer> ma = new TreeMap<Character,Integer> ();String strs = "";for(int i = 0;i<ch.length;i++){//判断键是否存在Integer value = ma.get(ch[i]);//如果存在次数加1,如果不存在次数为1value = (value==null)?1:(++value);ma.put(ch[i],value);}for(Iterator<Map.Entry<Character,Integer>> it = ma.entrySet().iterator();it.hasNext();){Map.Entry<Character,Integer> me = it.next();strs+= me.getKey()+"("+me.getValue()+"),";}return strs;}}
七、Map集合扩展
      
/*需求:有一个学校,这个学校有两个班级,每个班级有两名学生,用代码实现打印每个班级吗名称及学生map扩展知识。map集合被使用是因为具备映射关系。"yureban"   Student("01" "zhangsan");"yureban" Student("02" "lisi");"jiuyeban" "01" "wangwu";"jiuyeban" "02" "zhaoliu";一个学校有多个教室。每一个教室都有名称。*///定义学生类import java.util.*;class Student implements Comparable<Student>{private String name;private String sex;public Student(String name,String sex){this.name = name;this.sex = sex;}public String getName(){return name;}public String getSex(){return sex;}public boolean equals(Object obj){if(!(obj instanceof Student))throw new ClassCastException("类型不匹配");return this.name.equals(((Student)obj).name)&&this.sex.equals(((Student)obj).sex); }public int hashCode(){return this.name.hashCode()+sex.hashCode()*21;}public int compareTo(Student stu){int num = this.name.compareTo(stu.name);if(num == 0)return new Integer(this.sex).compareTo(new Integer(stu.sex));return num;}}class  MapDemo4{public static void main(String[] args) {/*----第一种------*//*//创建学校集合Map<String,Map<String,Student>> czbk = new TreeMap<String,Map<String,Student>>();//创建基础班集合Map<String,Student> caseStudent = new TreeMap<String,Student>();//创建高级班集合Map<String,Student> advStudent = new TreeMap<String,Student>();//把班级添加到学校所在的集合czbk.put("case",caseStudent);czbk.put("adv",advStudent);//基础班添加学生信息caseStudent.put("c01",new Student("ZhangSan","man"));caseStudent.put("c02",new Student("Lisi","woman"));//高级班添加学生信息advStudent.put("a01",new Student("WangWu","man"));advStudent.put("a02",new Student("ZhaoLiu","Woman"));//使用迭代遍历学校for(Iterator<Map.Entry<String,Map<String,Student>>> it = czbk.entrySet().iterator();it.hasNext();){Map.Entry<String,Map<String,Student>> me = it.next();//打印班级名System.out.println(me.getKey());//获取班级信息Map<String,Student> ma = me.getValue();//遍历班级信息for(Iterator<Map.Entry<String,Student>> iter = ma.entrySet().iterator();iter.hasNext();){Map.Entry<String,Student> mes = iter.next();//获取学生信息Student stu = mes.getValue();//打印学生信息System.out.println(mes.getKey()+"=="+stu.getName()+":"+stu.getSex());}}*//*------第二种-比较常用-----*///创建学校集合Map<String,List<Student>> czbk = new TreeMap<String,List<Student>>();//创建基础班集合List<Student> caseStudent = new ArrayList<Student>();//创建高级班集合List<Student> advStudent = new ArrayList<Student>();//把班级添加到学校所在的集合czbk.put("case",caseStudent);czbk.put("adv",advStudent);//基础班添加学生信息caseStudent.add(new Student("ZhangSan","man"));caseStudent.add(new Student("Lisi","woman"));//高级班添加学生信息advStudent.add(new Student("WangWu","man"));advStudent.add(new Student("ZhaoLiu","Woman"));getShow(czbk);}public static void getShow(Map<String,List<Student>> ma){for(Iterator<String> it = ma.keySet().iterator();it.hasNext();){String key = it.next();System.out.println(key);List<Student> stu = ma.get(key);for(Iterator<Student> iter = stu.iterator();iter.hasNext();){Student st =iter.next();System.out.println(st.getName()+":"+st.getSex());}}}}
Collections工具类

一、概述

        Collections是对集合框架的一个工具类。它里边的方法都是静态的,不需要创建对象。并未封装特有数据。

       Collections工具类中大部分方法是用于对List集合进行操作的,如比较,二分查找,随机排序等

二、Collection和Collections的区别

Collection是集合框架中的一个顶层接口,它里面定义了单列集合的共性方法。
        它有两个常用的子接口,
        List:对元素都有定义索引。有序的。可以重复元素。
        Set:不可以重复元素。无序。

Collections是集合框架中的一个工具类。该类中的方法都是静态的
        提供的方法中有可以对list集合进行排序,二分查找等方法。
        通常常用的集合都是线程不安全的。因为要提高效率。
        如果多线程操作这些集合时,可以通过该工具类中的同步方法,将线程不安全的集合,转换成安全的。

三、常用方法

1、增加

1、addAll(Collection<? super T> c, T... elements)     将所有指定元素添加到指定 collection 中。

2、获取

1、binarySearch(List<? extendsComparable<? super T>> list, T key) 

       返回要查询的指定元素在list集合中的位置,如果没有返回插入点
2、binarySearch(List<? extends T> list, T key, Comparator<? super T> c)

       指定一个比较器,返回要查询的指定元素在排序后List集合中的位置,如果没有,返回插入点

3、frequency(Collection<?> c,Object o)
          返回指定 collection 中等于指定对象的元素数。

4、indexOfSubList(List<?> source,List<?> target)
          返回指定源列表中第一次出现指定目标列表的起始位置;如果没有出现这样的列表,则返回 -1。

5、lastIndexOfSubList(List<?> source,List<?> target)
          返回指定源列表中最后一次出现指定目标列表的起始位置;如果没有出现这样的列表,则返回 -1。

6、shuffle(List<?> list)
          使用默认随机源对指定列表进行置换。

3、Copy

1、copy(List<? super T> dest,List<? extends T> src)
          将所有元素从一个列表复制到另一个列表。

4、判断

1、disjoint(Collection<?> c1,Collection<?> c2)
          如果两个指定 collection 中没有相同的元素,则返回 true

5、替换

1、fill(List<? super T> list, T obj)
          使用指定元素替换指定列表中的所有元素。

2、replaceAll(List<T> list, T oldVal, T newVal)
          使用另一个值替换列表中出现的所有某一指定值。

6、反转

1、reverse(List<?> list)
          反转指定列表中元素的顺序。

7、获取最值

1、max(Collection<? extends T> coll)
          根据元素的自然顺序,返回给定 collection 的最大元素。

2、max(Collection<? extends T> coll, Comparator<? super T> comp)
          根据指定比较器产生的顺序,返回给定 collection 的最大元素。

3、min(Collection<? extends T> coll)
          根据元素的自然顺序 返回给定 collection 的最小元素。

4、min(Collection<? extends T> coll, Comparator<? super T> comp)
          根据指定比较器产生的顺序,返回给定 collection 的最小元素。

8、比较器

1、reverseOrder()
          返回一个比较器,它强行逆转实现了 Comparable 接口的对象 collection 的自然顺序

2、reverseOrder(Comparator<T> cmp)
          返回一个比较器,它强行逆转指定比较器的顺序。

9、排序

1、sort(List<T> list)
     根据元素的自然顺序 对指定列表按升序进行排序。

2、sort(List<T> list,Comparator<? super T> c)
          根据指定比较器产生的顺序对指定列表进行排序。

3、

10、换位

1、swap(List<?> list, int i, int j)
          在指定列表的指定位置处交换元素。


11、线程同步

1、synchronizedCollection(Collection<T> c)
          返回指定 collection 支持的同步(线程安全的)collection。

2、synchronizedList(List<T> list)
          返回指定列表支持的同步(线程安全的)列表。

3、synchronizedMap(Map<K,V> m)
          返回由指定映射支持的同步(线程安全的)映射。

4、synchronizedSet(Set<T> s)
          返回指定 set 支持的同步(线程安全的)set。

练习:
/*需求:使用Collections中的方法fill对List集合中的部分元素进行替换 思路:1、将List集合中要替换的部分元素取出,并存入另一集合中       2、使用removeAll方法取交集      3、用fill将要替换的元素进行替换       4、将取出的部分增加进集合 */import java.util.*;class  CollectionsFillTest {      public static void main(String[] args)       {          List<String> list = new ArrayList<String>();            list.add("abc");          list.add("ab");          list.add("abcd");          list.add("a");          list.add("abcdef");list.add("abcdeg");list.add("abcdeh");list.add("abcdes");list.add("abcdeb");fillSome(list,1,3,"mk");        System.out.println(list);      }  public static void fillSome(List<String> list,int start,int end,String key){if(start>=end)throw new InputException("要替换的元素间隔不正确");List<String> li = new ArrayList<String>();for(int i=start;i<end;i++){li.add(list.get(i));}list.removeAll(li);Collections.fill(li,key);list.addAll(start,li);}}class InputException extends RuntimeException{public InputException(String message){super(message);}}
Arrays工具类

一、概述

        Arrays是用于操作数组的工具类。里边的方法也全是静态的。不需要创建对象。

       把数组变成List集合的好处:可以使用集合的思想和方法来操作数组中的元素。如:containsgetindexOfsubList等方法。

二、常用方法

1、数组变集合(asList方法)

1、asList(T... a)
          将数组转换成List集合

把数组变成list集合有什么好处?
        可以使用集合的思想和方法来操作数组中的元素。
        注意:将数组变成集合,不可以使用集合的增删方法。
        因为数组的长度是固定。
        contains。
        get
        indexOf()
        subList();
        如果你增删。那么会反生UnsupportedOperationException,

练习:

import java.util.*;class  ArraysDemo{public static void main(String[] args) {String[] arr = {"abc","cc","kkkk"};List<String> list = Arrays.asList(arr);sop("contains:"+list.contains("cc"));//list.add("qq");//UnsupportedOperationException,  不能使用集合的增删方法sop(list);//int[] nums = {2,4,5};                 <code></code><pre name="code" class="java">/*如果数组中的元素都是对象。那么变成集合时,数组中的元素就直接转成集合中的元素。如果数组中的元素都是基本数据类型,那么会将该数组作为集合中的元素存在。*/
 Integer[] nums = {2,4,5};List<Integer> li = Arrays.asList(nums);sop(li);}public static void sop(Object obj){System.out.println(obj);}}

2、集合变数组(toArray方法
/*集合变数组。Collection接口中的toArray方法。*/import java.util.*;class  CollectionToArray{public static void main(String[] args) {ArrayList<String> al = new ArrayList<String>();al.add("abc1");al.add("abc2");al.add("abc3");/*1,指定类型的数组到底要定义多长呢?当指定类型的数组长度小于了集合的size,那么该方法内部会创建一个新的数组。长度为集合的size。当指定类型的数组长度大于了集合的size,就不会新创建了数组。而是使用传递进来的数组。所以创建一个刚刚好的数组最优。2,为什么要将集合变数组?为了限定对元素的操作。不需要进行增删了。*/String[] arr = al.toArray(new String[al.size()]);System.out.println(Arrays.toString(arr));}}

小知识


一、高级for

1、格式:

        for(数据类型变量名 :被遍历的集合(collection)或者数组) {执行语句}

2、说明

        a、对集合进行遍历。只能获取集合元素。但是不能对集合进行操作。可以看作是迭代器的简写形式。

        b、迭代器除了遍历,还可以进行remove集合中元素的动作。如果使用ListIterator,还可以在遍历过程中对集合进行增删改查的操作。

3、传统for和高级for的区别:

        高级for有一个局限性。必须有被遍历的目标(集合或数组)。

        传统for遍历数组时有索引。

        建议在遍历数组的时候,还是希望使用传统for。因为传统for可以定义角标。

示例:

     
class For  {      public static void main(String[] args)       {          //定义一个ArrayList集合          ArrayList<String> al = new ArrayList<String>();          al.add("abc1");          al.add("abc2");          al.add("abc3");            for(String s : al)          {              System.out.println(s);//用高级for遍历集合          }            //传统for与高级for遍历数组          int[] arr = {3,5,1};            for(int x=0; x<arr.length; x++)          {              System.out.println(arr[x]);          }          for(int i : arr)          {              System.out.println("i:"+i);          }            //定义一个HashMap集合          HashMap<Integer,String> hm = new HashMap<Integer,String>();            hm.put(1,"a");          hm.put(2,"b");          hm.put(3,"c");            //keySet取出方式的高级for遍历          Set<Integer> keySet = hm.keySet();          for(Integer i : keySet)          {              System.out.println(i+"::"+hm.get(i));          }            //entrySet取出方式的高级for遍历          for(Map.Entry<Integer,String> me : hm.entrySet())          {              System.out.println(me.getKey()+"------"+me.getValue());          }        }  }


 

二、方法的可变参数

        如果一个方法在参数列表中传入多个参数,个数不确定,那么每次都要复写该方法。这时可以用数组作为形式参数。但是在传入时,每次都需要定义一个数组对象,作为实际参数。在JDK1.5版本后,就提供了一个新特性:可变参数。

        可变参数其实就是数组参数的简写形式。不用每一次都手动的建立数组对象。只要将要操作的元素作为参数传递即可。隐式将这些参数封装成了数组。

        在使用时注意:可变参数一定要定义在参数列表的最后面。

示例:

    
{      public static void main(String[] args)       {          show("haha",2,3,4,5,6);      }      public static void show(String str,int... arr)//...就表示可变参数      {          System.out.println(arr.length);      }  }   


 

三、静态导入

1、写法:

        import staticjava.util.Arrays.*;//导入的是Arrays这个类中的所以静态成员。

        import staticjava.lang.System.*//导入了Ssytem类中所以静态成员。

       没加static导入的是类,加上static导入的全是某一个类中所以的静态成员。这样写在调用该类的静态方法时可以不用再写类名。如:Arrays.sort(数组);就可以直接写sort(数组);

2、注意:

        当导入的两个类中有同名成员时,需要在成员前加上相应的类名。

       当类名重名时,需要指定具体的包名。当方法重名时,指定具体所属的对象或者类。

示例:

      
class  StaticImport //extends Object  {      public static void main(String[] args)       {            out.println("haha");//打印输出时就可以直接省略书写System.          int[] arr = {3,1,5};            sort(arr);//使用Arrays工具类的方法sort时就可以省略书写Array.            int index = binarySearch(arr,1);//半分查找也是一样可以省略          out.println("Index="+index);            //当没有指定继承时,所以类默认继承了Object,         //因为toString方法都具备,所以为了区分,必须写上具体调用者         out.println(Arrays.toString(arr));      }  }  





















0 1
原创粉丝点击