您的位置:首页 > 职场人生

黑马程序员Java学习日记(5)集合(二)

2014-07-19 21:20 459 查看
------- <a href="http://www.itheima.com" target="blank">android培训</a>、<a href="http://www.itheima.com" target="blank">java培训</a>、期待与您交流! ----------

1.Map集合:

(1)Map集合的特点:

     1、接口Map<k,v>:必须存2个元素,而且两个元素之间有映射关系。

     2、该集合存储键值对,一对一对的往里存,需要保证键的唯一性。

     3、是一个双列集合,Collection是单列集合。

(2)Map集合的常用方法:

     1、添加:V put(K key, V value);  

              void  putAll(Map<? extends K,? extends V> m);

              Put方法的特点:如果要添加的键在集合中已经存在了,那么会

                             覆盖以前的键,并且会将以前的值返回。

     2、删除: void clear();

              V remove(Object key);     

   

     3、判断:boolean isEmpty();

             boolean containsKey(Object key);

             boolean containsValue(Object value);

             boolean equals(Object o);

        

     4、获取:V  get(Object key);

             int hasCode();

             int size();

             Collection<V>  values();

             Set<Map.Entry<K,V>>  entrySet();

             Set<k> keySet(); 

 

(3)Map集合的子类:

     1、HashMap: 

                底层是哈希表数据结构,允许使用null键和null值,该集合

        是不同步的,效率高。

 

     2、TreeMap: 

                底层是二叉树数据结构,线程不同步,可以给Map集合中的

        键进行排序。

 

     3、Hashtable: 

                底层是哈希表数据结构,线程同步,不可以存入null键和

        null值,该集合是线程同步的。为了成功的在哈希表中存储和获取对象,

        用做键的对象 必须实现hashCode和equals方法。

(4)Map集合的取出方式一: 

 keySet();方法:

代码例子:

import java.util.*;

class MapDemo1 

{

    public static void main(String[] args) 

    {

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

        map.put("02","zhangsan");

        map.put("05","lisi");

        map.put("06","wangwu");

        map.put("01","zhaoliu");

        //获取Map集合所有键的Set集合。

       Set<String> keySet =map.keySet();

       //获取到Set集合就可以用迭代器迭代了。

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

        while(it.hasNext())

       {   

            //Set集合中取出的是所有的键。

            String key =it.next();

            //获取到键以后就可以用Map集合的get方法获取其对应的值。

           String value =map.get(key);

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

        }

     }

}

                 

(5)Map集合的取出方式二:     

  entrySet();

  代码例子:

  import java.util.*;

class MapDemo2 

{

     public static void main(String[] args) 

     {

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

         map.put("02","zhangsan");

         map.put("05","lisi");

         map.put("06","wangwu");

         map.put("01","zhaoliu");

 

        //将Map集合中的映射关系取出存入Set集合。

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

       //用迭代器进行迭代。

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

        while(it.hasNext())

         {

               //取出的是Map集合中的映射关系。

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

               //获取键,通过Map.Entry中的getKey()方法。

                String key = kv.getKey();

               //获取值,通过Map.Entry中的getValue()方法。

                String value =kv.getValue();

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

          }

      }

}

     

注意:Map.Entry也是一个接口,它是Map集合中的一个内部接口。

代码例子:

interface Map

{  

      //是Map的内部接口,并且是静态的,对外公开,也能够产生class文件。 

     public static interface Entry

     {  

       public abstract void getKey();

       public abstract void getValue();

      }



 

class HashMap implements Map

{
      //内部类实现了Entry。

     class Hash implements Map.Entry

     {

        //复写了接口接口中的抽象方法。

        public void getKey(){}

        public void getValue(){}

      }

}

 

(6)练习一

  需求:实现自定一个学生对象和地址,使用HashMap。

           学生:Student  地址:String

           学生属性:姓名,年龄

           注意:同姓名同年龄为同一个人

          需要保证学生的唯一性

  代码例子:

import java.util.*;

class  Student implements Comparable<Student>

{

    private String name;

    private int age;

    Student(String name,int age)

    {

        this.name=name;

        this.age=age;

     }

     public void setName(String name)

     {

        this.name=name;

     }

     public void setAge(int age)

     {

       this.age=age;

      }

      public String getName()

      {

          return name;

       }

      public int getAge()

      {

        return age;

       }

         //复写equals方法。

      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;

        }

        //复写hashCode方法。

        public int hashCode()

        {

           return name.hashCode()+age*34;

         }

               /*复写compareTo方法,让元素具备自然顺序,因为有可能存到 TreeMap集合中。*/

 

         public int compareTo(Student s)

        {

           int num =new Integer(this.age).compareTo(new Integer(s.age));

           if(num==0)

              return this.name.compareTo(s.name);

           return num;

         }

}

class MapTest1

{

     public static void main(String[] args) 

     {

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

        map.put(new Student("lisi1",21),"beijing");

        map.put(new Student("lisi2",22),"shanghai");

        map.put(new Student("lisi3",23),"guangdong");

        map.put(new Student("lisi4",24),"wuhan");

       

        //获取Map集合所有键的Set集合。

        Set<Student> keySet= map.keySet();

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

         while(it.hasNext())

         {

                //取出的是学生对象。

                Student stu=it.next();

                //根据取出的学生对象键,获取到地址。

                String addr=map.get(stu);

                System.out.println(stu.getName()+".."+stu.getAge()+".."+addr);

          }

      }

}

 

打印结果:

          lsi4..24..wuhan

          lisi2..22..shanghai

          lisi1..21..beijing

          lisi3..23..guangdong

  

(7)练习二

 需求:对(6)中学生对象的年龄进行升序排序。

       使用TreeMap集合。

代码例子:将(6)中的集合改成TreeMap。

 class MapTest2

{

    public static void main(String[] args) 

   {

        Map<Student,String> map =new TreeMap<Student,String>();

        map.put(new Student("lisi1",21),"beijing");

        map.put(new Student("lisi2",22),"shanghai");

        map.put(new Student("lisi3",23),"guangdong");

        map.put(new Student("lisi4",24),"wuhan");

       

          //获取Map集合所有键的Set集合。

       Set<Student> keySet= map.keySet();

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

         while(it.hasNext())

         {

              //取出的是学生对象。

             Student stu=it.next();

             //根据取出的学生对象键,获取到地址。

             String addr=map.get(stu);

            System.out.println(stu.getName()+".."+stu.getAge()+".."+addr);

           }

     }

}

 

打印结果为:

             lisi1..21..beijing

             lisi2..22..shanghai

             lisi3..23..guangdong

             lisi4..24..wuhan

 

(8)练习三

  需求:获取字符串中的字母出现的次数。

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

  发现每一个字母都有对应的次数,说明字母与数字之间有映射关系,

  所以可以使用Map集合。

 步骤:

 1、将字符串转换成字符数组,因为要对每一个字母进行操作。

 2、定义一个Map集合,使用TreeMap因为打印结果有顺序。

 3、将每一个字母作为键去查Map集合,如果返回的是null,

   就将该字母和1存入到Map集合中,如果返回的不是null,

   说明字母已经在集合中存在了并且对应了次数,那么就获取

   该次数进行自增,然后将自增后的字母和次数存入到集合中。

 4、将Map集合中的数据按照指定的字符串返回。

                                  

 代码例子:

 import java.util.*;

class MapTest3

{

     public static void main(String[] args) 

     {

        String s =charCount("abchacbdf");

        System.out.println(s);

      }

      public static String charCount(String str)

      {

            char[] chs = str.toCharArray();

           TreeMap<Character,Integer> tm= new TreeMap<Character,Integer>();

            for(int x=0; x<chs.length; x++)

            { 

                 if(!(chs[x]>='a'&&chs[x]<='z'||chs[x]>='A'&&chs[x]<='Z'))

                 continue; 

                 Integer value =tm.get(chs[x]);

                 if(value==null)

                 {

                    //count = value;

                    tm.put(chs[x],1);

                   }

                   else

                   {

                       value = value+1;

                        tm.put(chs[x],value);

                     }   

               } 

            StringBuilder sb =new StringBuilder();

            Set<Map.Entry<Character,Integer>> entryKey=tm.entrySet();

            Iterator<Map.Entry<Character,Integer>> it=entryKey.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();  

          } 

  }

2.Map集合扩展知识:

需求:集合嵌套集合,

      有一个学校,学校有两个班,每个班有二个学生,有学号和姓名。

      取出这学校所以班的所有学生。

代码例子:

import java.util.*;

class  Student  //定义一个学生类。

{

    private String name;

    private String id;

    Student(String name,String id)

    {

        this.name=name;

        this.id=id;

     }

     public void setName(String name)

     {

         this.name=name;

      }

      public void setId(String id)

      {

           this.id=id;

       }

       public String getId()

       {

         return id;

        }

       public String getName()

       {

            return name;

        }

}

class MapTest4

{

     public static void main(String[] args)

     {

         //班级与学生产生映射关系,所以用Map集合定义学校。

          HashMap<String,List<Student>> xuexiao =

                                   new HashMap<String,List<Student>>();

          //用List集合定义班级来存储学生对象。

          List<Student> yiban =new ArrayList<Student>();

           //一班有两个学生。

          yiban.add(new Student("01","zhangsan"));

          yiban.add(new Student("02","lisi"));

          List<Student> erban =new ArrayList<Student>();

          //二班有两个学生。

          erban.add(new Student("01","wangwu"));

          erban.add(new Student("02","zhaoliu"));

          //将这个两个班级添加进Map集合,也就是学校。

          xuexiao.put("yiban",yiban);

          xuexiao.put("erban",erban);

          //遍历Map集合,将键取出,也就是将学校取出。

          Iterator<String> it= xuexiao.keySet().iterator();

           while(it.hasNext())

           {

               String roomname =it.next();

               //根据键获取值,也就是获取学生对象。

               List<Student> room = xuexiao.get(roomname);

              System.out.println(roomname);

               getInfos(room);     

             }

     }

     public static void getInfos(List<Student> list)

     {

           //遍历List集合,取出学生的学号和姓名。

           Iterator<Student> it1 =list.iterator();

           while(it1.hasNext())

           {

              Student s =it1.next();

              System.out.println(s.getId()+".."+s.getName());

            }

        }

}

打印结果为:

           
yiban

            01..zhangsan

            02..lisi

            erban

            01..wangwu

            02..zhaoliu

3.Collections 集合工具类:

(1)Collection与Collections的集合的区别:

     Collection是一个接口,里面是包含了各种集合容器。

     Collections是一个工具类,里面包含了各种用来操作Collection实例类的

     的方法,里面的方法都是静态的,泛型要定义在方法上,可以对List集合

     进行排序。

(2)Collections里面有那些常用的方法:

     1、sort()

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

        collection 的最大元素。

        max(Collection<? extends T> coll, Comparator<? super T> comp)

        根据比较器产生的顺序,返回给定 collection 的最大元素。

        

     3、binarySearch(List<? extends Comparable<? super T>> list,T key)

        接收的是自然顺序比较。

        binarySearch(List<? extends T> list, T key,Comparator<? super T> c)

        接收的是比较器。

 

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

 

     5、replaceAll(List<T> list, T oldVal, T newVal) 使用另一个值替换列表中出现

        的所有某一指定值。

     6、reverseOrder()返回一个比较器,它强行逆转实现了Comparable 接口的

        对象 collection 的自然顺序。 

 注意:使用二分搜索法搜索指定列表,以获得指定对象。必须是List集合,因为涉及到角标,而且集合必须是有序的

      才能使用这个方法。               

(3)sort方法的应用:

  是给List集合排序用的,比如我们在List集合里面存了一个学生对象,那我们要用Collections里面的sort方法对List集合

 进行排序,但是学生对象不具备比较性,那么就绪要泛型限定:

代码例子:

public static<T extends Comparable<? super T >> void sort(List<T> list){}

T必须是Comparable的子类,也就是必须实现Comparable,Comparable里面还可以传T或者T的父类。在比较的时候调用了Comparable内部的compareTo方法。

代码例子:

1、自然排序:

import java.util.*;

class CollectionsDemo 

{

      public static void main(String[] args) 

      {

        sortDemo();

      }

      public static void sortDemo()

      {

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

       al.add("abcd");

       al.add("aaa");

       al.add("z");

       al.add("kkkk");

       al.add("qq");

       Collections.sort(al);

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

       while(it.hasNext())

       {

          String s =it.next();

          System.out.println(s);

        }

     }

}

打印结果为:

            aaa

            abcd

            Kkkk

            qq

            z

 

2、如果按照长度排序,需要定义一个比较器,实现Comparator接口。

代码例子:

import java.util.*;

class CollectionsDemo1 

{

     public static void main(String[] args) 

     {

          sortDemo();

     }

     public static void sortDemo()

     {

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

           al.add("abcd");

           al.add("aaa");

           al.add("bbb");

           al.add("z");

           al.add("kkkk");

           al.add("qq");

            //往sort集合中传一个比较器对象。

           Collections.sort(al,new CollectionsDemo2());

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

            while(it.hasNext())

            {

              String s =it.next();

              System.out.println(s);

             }

        }

}

//实现Comparator接口。

class CollectionsDemo2 implements Comparator<String>

{

        //覆盖compare方法。

       public int compare(String s1,String s2)

       {    

             int num=new Integer(s1.length()).compareTo(new Integer(s2.length()));

             if(num==0)

                return s1.compareTo(s2);

             return num;

         }

}

打印结果:

          z

 

          qq

          aaa

          bbb

          abcd

          kkkk

 

(4)Max方法的应用:

  import java.util.*;

class CollectionsDemo1 

{

     public static void main(String[] args) 

     {

        maxDemo();

      }

      public static void maxDemo()

      {

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

            al.add("abcd");

            al.add("aaa");

            al.add("bbb");

            al.add("z");

            al.add("kkkk");

            al.add("qq");

            String max =Collections.max(al);

            System.out.println(max);

}

打印结果是:z

如果加上比较器:

代码改成:

String max =Collections.max(al,new CollectionsDemo2());

class CollectionsDemo2 implements Comparator<String>

{

      public int compare(String s1,String s2)

      {    

          int num=new Integer(s1.length()).compareTo(new Integer(s2.length()));

          if(num==0)

             return s1.compareTo(s2);

          return num;

       }



打印的结果是
kkkk

也就是打印的长度最大的元素。

(5)binarySearch方法的应用:

1、代码例子:

import java.util.*;

class CollectionsDemo3 

{

      public static void main(String[] args) 

      {

         indexDemo();

      }

      public static void indexDemo()

      {

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

           al.add("aaa");

           al.add("abcd");

           al.add("bbb");

           al.add("kkkk");

           al.add("qq");

           al.add("z");

           //调用binarySearch查找”z”。

           int index =Collections.binarySearch(al,"z");

           //打印结果为5。

           System.out.println(index);

        }

}

注意:如果查找的是”zz”,那么打印结果就是-7,当要查找的元素不存在时,就返回负数,这个负数就是插入点前面价格负数再减一,插入点就是指如果这个元素存在于集合中,那么它应该存在于什么位置,这个位置就是插入点。

 

如果List集合中的元素不具备比较性,也就是没有实现Comparable接口,那么就用binarySearch方法的第二种形式,里面接收的是一个比较器。

2、那么代码改成:

import java.util.*;

class CollectionsDemo3 

{

    public static void main(String[] args) 

    {

       indexDemo();

    }

    public static void indexDemo()

    {

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

       al.add("aaa");

       al.add("abcd");

       al.add("bbb");

       al.add("kkkk");

       al.add("qq");

       al.add("z");

       //调用binarySearch形式2查找”z”。

       int index =Collections.binarySearch(al,"z",new CollectionsDemo4());

        //打印结果为5。

       System.out.println(index);

     }

}

 

class CollectionsDemo4 implements Comparator<String>

{

    public int compare(String s1,String s2)

   { 

         int num=new Integer(s1.length()).compareTo(new Integer(s2.length()));

         if(num==0)

           return s1.compareTo(s2);

         return num;

      }

}

 

 (6)fill方法的应用:

 代码例子:

 import java.util.*;

 class CollectionsDemo5

 {

      public static void main(String[] args) 

      {

          //sortDemo();

          fillDemo();

       }

       public static void fillDemo()

       {

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

          al.add("aaa");

          al.add("abcd");

          al.add("bbb");

          //调用Collections中的fill方法将List集合中的全部元素都替换成”pp”。

          Collections.fill(al,"pp");

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

           while(it.hasNext())

           {

              String s=it.next();

              System.out.println(s);

            }

       }

}    

打印的结果是:

             
pp

              pp

              pp 

如果想替换部分元素,那么就分别设置就行,al.set(0,”pp”);

 

(7)replaceAll方法的应用:

 代码例子:

 import java.util.*;

class CollectionsDemo6

{

     public static void main(String[] args) 

     {

         //sortDemo();

         int start=0;

         int end =3;

         replaceAllDemo();

      }

      public static void replaceAllDemo()

      {

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

           al.add("aaa");

           al.add("abcd");

           al.add("bbb");

           //调用Collections中的replaceAll方法将集合中的元素”bbb”替换成”www”。

          Collections.replaceAll(al,"bbb","www");

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

          while(it.hasNext())

           {

              String s=it.next();

              System.out.println(s);

            }

       }

}

打印结果为:

           
aaa

            abcd

            www

 

(8)reverseOrder方法的应用:

 代码例子:

import java.util.*;

class CollectionsDemo7

{

    public static void main(String[] args) 

    { 

        reverseOrderDemo();

     }

     public static void reverseOrderDemo()

     {

       /*在TreeSet的构造函数中接收一个Collections的reverseOrder方法返回 

        
一个比较器,它强行逆转实现了 Comparable 接口的对象 collection 的

        
自然顺序。*/       

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

          ts.add("aaa");

          ts.add("abcd");

          ts.add("bbb");

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

          while(it.hasNext())

          {

             String s=it.next();

            System.out.println(s);

           }

       }

}

打印结果为:

            
bbb

            abcd

            aaa

 

4.Arrays工具类:

Arrays工具类的作用:用于操作数组的工具类,里面都是静态方法。

(1)将数组变成List集合:

用到了Arrays中的asList方法。

将数组变成List集合的好处:

   1、可以使用集合的思想和方法操作数组中的元素。

   2、数组是一个对象,功能比较少,List是一个集合功能比较多。

注意:将数组变成List集合,不可以使用集合的增删方法,因为数组的的长度

      是固定的。

代码例子:

import java.util.*;

class ArraysDemo 

{

    public static void main(String[] args) 

   {

          //定义一个字符串数组。

          String[] arr={"abc","cc","kkkk"};

          //调用Arrays中的asList方法,将数组变成List集合。

          List<String> list =Arrays.asList(arr);

          System.out.println(list);

     }

}

打印结果为:[abc,cc,kkkk]

 

如果定义一个int型的数组呢?

代码例子:

import java.util.*;

class ArraysDemo 

{

       public static void main(String[] args) 

       {

          int[] num={1,2,3,4};

          List<int[]> list =Arrays.asList(num);

          System.out.println(list);

        }

}

打印结果为:哈希值。

那么为什么呢?

因为如果数组中的元素都是对象的话,那么就可以直接转成集合中的元素,就如同String数组,如果数组里面的元素都是基本数据类型,那么会将该数组作为集合中的元素存在。

 

如果写成是Integer数组的话,就可以了,因为Integer有自动装箱和拆箱的功能。

代码例子:

import java.util.*;

class ArraysDemo 

{

     public static void main(String[] args) 

     {

           Integer[] num={1,2,3,4};

           List<Integer> list =Arrays.asList(num);

           System.out.println(list);

       }

}

//打印结果为:[1,2,3,4]

 

(2)集合转成数组。

用的是Collection接口中的toArrayT[] a方法,

代码例子:

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

 

      /*将集合变成数组,指定一个集合中元素的个数,

     也就是指定数组的长度。*/

       String[] arr = al.toArray(new String[al.size()]);

       //以字符串的形式打印出来。

       System.out.println(Arrays.toString(arr));

   }

}

//打印结果为:[abc1,abc2,abc3]

 

那么指定类型的数组长度到底定义多长呢?

    1、当指定的长度小于集合的长度,该方法内部会自动创建一个该类型的新数
         组长度和集合长度一致 。用于存储集合中的元素。
    2、如果指定的数组长度大于集合的长度,那么该方法就不会创建新数组。而
        
是使用传递进来的数组,存储完集合的元素后,其他的未存储的位置为null。
 
    3、所以在定义数组是,最好定义长度和集合长度相同的数组,这样就不用创建新数组了,而且也不会出现空位为
         
null 。
 
那么为什么要将集合变成数组?
     是为了限定对元素的操作,变成数组以后就不能进行增删操作了。
            
------- <a href="http://www.itheima.com" target="blank">android培训</a>、<a href="http://www.itheima.com" target="blank">java培训</a>、期待与您交流! ----------

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息