zoukankan      html  css  js  c++  java
  • 黑马程序员----java基础--集合

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

    一、集合类的描述

      面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一种方式。数组虽然也可以存储对象,但长度是固定的;集合长度是可变的。数组中可以存储基本数据类型,集合只能存储对象。数组很难对其数据进行操作,而集合可以很方便对存储的对象进行增删改查等操作。可以说集合比数组功能更加强大而且使用起来也更加方便。所以我们有必要深入的学习一下集合类。

    集合的特点:

    (1)、用于存储对象的容器

    (2)、集合的长度是可变的

    (3)、集合中不可以存储基本数据类型值

    (4)、集合中存储的都是对象的引用(地址)

    二、集合框架的构成以及分类

    根据数据结构的不同,可以分为不同的集合(容器)。下图是集合框架构成图。

    从途中可以看出集合类主要分为两大接口:1、Collection接口 2、Map接口。

    Collection接口

      |--List集合:元素都是有序的(存入和取出的顺序一致),元素是可以重复的,因为该集合体系具有索引。

        |--ArrayList:底层的数据结构使用的是数组结构。特点:查询速度快,但增删稍慢,线程不同步。

        |--LinkedList:底层使用的是链表数据结构。特点:增删速度很快,查询稍慢,线程不同步。

        |--Vector:底层是数组数据结构,线程同步,已被ArrayList替代了,因为效率低。

      |--Set集合:元素是无序的(存入和取出的顺序不一定一致),元素不可重复。Set接口中的方法和Collection接口中的方法一致。

        |--HashSet集合:底层数据结构是哈希表,线程不安全,不同步。

          |--LinkedHashSet:底层是链式的哈希表,该集合特点:存入数据和取出数据顺序一致,而且元素不重复,线程不同步。

        |--TreeSet:底层是二叉树数据结构,可以对Set集合中的元素进行排序,线程不同步。

    Map接口

      |--Hashtable集合:底层是哈希表数据结构,不可以存入null键null值,该集合是线程同步的,效率低。JDK1.0出现的。

        |--Properties集合:用来存储键值对型的配置文件的信息,可以和IO技术相结合。

      |--HashMap集合:底层是哈希表数据结构,允许使用null键null值,该集合是不同步的。该集合替换了Hashtable集合,效率高。JDK1.2出现的。

        |--LinkedHashMap集合:底层是链式的哈希表结构,使用LinkedHashMap存入和取出的顺序是一致的。

      |--TreeMap集合:底层是二叉树数据结构,线程不同步。可以用于给Map集合中的键进行排序。

    Java集合类大部分的都增加了泛型,已增加程序的安全性,以后会详细的介绍的。了解了集合类的大致下面我们具体的介绍这几大集合类。

    三、Collection<E>接口

    Collection是集合框架中的常用接口。其下有两个子接口:List(列表),Set(集)。

    1、Collection集合集成体系:

      |--Lsit

        |--ArrayList

        |--LinkedList

        |--Vector

      |--Set

        |--HashSet

          |--LinkedHashSet

        |--TreeSet

    2、Collection接口常见的方法

    (1)、添加元素

    1 boolean  add(Object obj);//往集合中添加元素
    2 boolean  addAll(Collection c);//将另一Collection集合中的所有元素添加进Collection集合中

     (2)、删除元素

    1 boolean  remove(Object obj);//删除指定元素
    2 boolean  removeAll(Collection  con);//调用者只保留另一集合中没有的元素
    3 void clear();//清空Collection集合全部元素

     (3)、判断

    1 boolean  contains(Object obj);//判断集合中是否包含指定元素
    2 boolean  containsAll();//判断此Collection集合中是否包含另一个Collection集合
    3 boolean  isEmpty();//判断集合是否有元素

     (4)、获取

    1 int  siez();//获取集合的大小,其实就是在判断集合是否为空
    2 Iterator<E>   iterator();//获取Collection集合的迭代器

     (5)、获取交集

    1 boolean   retainAll(Collection c);//调用者只保留两集合的共性元素

     (6)、集合变数组

    1 Object[]   toArray();//把集合转换成数组
    2  <T> T[]  toArray(T[] a);//把集合转换成数组

      代码演示:

     1 import java.util.*;
     2 class CollectionDemo 
     3 {
     4     public static void main(String[] args) 
     5     {
     6         //因为Collection是接口无法创建对象,所以找子类来创建对象,多态的应用。
     7         Collection<String> c1=new ArrayList<String>();
     8         Collection<String> c2=new ArrayList<String>();
     9         add(c1);        
    10         addAll(c1,c2);
    11         remove(c1);
    12         removeAll(c1,c2);
    13     }
    14     //演示add方法
    15     public static void add(Collection<String> con){
    16         con.add("小明");
    17         con.add("赵四");
    18         con.add("王五");
    19         con.add("老王");
    20         con.add("黑马");
    21         con.add("安卓");
    22         //获取集合的大小
    23         System.out.println("size="+con.size());
    24         //打印一下集合
    25         System.out.println(con);
    26     }
    27     //演示addAll方法
    28     public static void addAll(Collection<String> co1,Collection<String>co2){
    29         co1.add("小明");
    30         co1.add("赵四");
    31         co1.add("王五");
    32         co1.add("钱峰");
    33 
    34         co2.add("黑马");
    35         co2.add("赵四");
    36         co2.add("钱峰");
    37         //将co2中的元素添加到co1中
    38         co1.addAll(co2);
    39         System.out.println("addAll:"+co1);
    40 
    41         //获取两个集合的交集,保留和指定的集合相同的元素
    42         co1.retainAll(co2);
    43         System.out.println("co1和co2取交集:"+co1);
    44     }
    45     //演示remove方法
    46     public static void remove(Collection<String> con){
    47         con.add("小明");
    48         con.add("赵四");
    49         con.add("王五");
    50         con.add("老王");
    51         con.add("黑马");
    52         con.add("安卓");
    53         System.out.println(con.remove("老王"));
    54         System.out.println(con.remove("java"));
    55         System.out.println("remove:"+con);
    56 
    57         //清空集合
    58         con.clear();        
    59         //判断集合是否为空
    60         System.out.println("con是否为空:"+con.isEmpty());
    61     }
    62     //演示removeAll方法
    63     public static void removeAll(Collection<String> co1,Collection<String>co2){
    64         co1.add("小明");
    65         co1.add("赵四");
    66         co1.add("王五");
    67         co1.add("老王");
    68 
    69         co2.add("老王");
    70         co2.add("赵四");
    71         co2.add("钱峰");
    72         //从co1集合中删除与co2集合相同的元素
    73         co1.removeAll(co2);
    74         System.out.println("removeAll:"+co1);
    75     }
    76     
    77 }

     3、Collection集合迭代器:Iterator<E>接口

    迭代器:是一个接口。作用:用于取集合中的元素。

      每一个集合都有自己的数据结构,都有特定的取出自己内部元素的方式。为了便于操作所有的容器,取出元素。将容器内部的取出方式按照一个统一的规则向外提供,这个规则就是Iterator接口。也就说,只要通过该接口就可以取出Collection集合中的元素,至于每一个具体的容器依据自己的数据结构,如何实现的具体取出细节,这个不用关心,这样就降低了取出元素和具体集合的耦合性。

     注:在迭代时循环中next调用一次,就要hasNext判断一次。

    获取Collection集中中元素的三种方式:

     1 import java.util.*;
     2 class CollectionDemo 
     3 {
     4     public static void main(String[] args) 
     5     {
     6         //因为Collection是接口无法创建对象,所以找子类来创建对象,多态的应用。
     7         Collection<String> c=new ArrayList<String>();
     8         c.add("小明");
     9         c.add("黑马");
    10         c.add("安卓");
    11         c.add("小明");
    12         c.add("王五");
    13         //用Collection中的iterator()方法。调用集合中的迭代器方法,是为了获取集合中的迭代器对象。
    14         //这种方式比较占用内存,因为循环结束后it变量还在内存中没有被释放        
    15         Iterator<String> it=c.iterator();
    16         while (it.hasNext())
    17         {
    18             String name=it.next();
    19             System.out.println(name);
    20         }
    21         
    22         //建议使用这种方法,不消耗内存空间,it变量在for循环中,循环结束变量也就消失了
    23         for (Iterator<String> it=c.iterator();it.hasNext() ; )
    24         {
            //Iterator中不能使用add添加方法,因为没有该方法,只能删除(remove)
    25 System.out.println(it.next()); 26 } 27 28 //这种方式是增强for循环,是Iterator迭代器的简写,但是这种方式有很大的弊端 29 //如果遍历Collection集合过程中还需要对元素进行操作,比如删除,需要使用迭代器。 30 for(String name:c){ 31 System.out.println(name); 32 33 } 34 }

     迭代注意事项

      (1)、迭代器在Collcection接口中是通用的,它替代了Vector类中的Enumeration(枚举)。

      (2)、迭代器的next方法是自动向下取元素,要避免出现NoSuchElementException。

      (3)、迭代器的next方法返回值类型是Object,所以要记得类型转换。加上泛型后则不需要转换。

    四、List<E>集合(接口)

    List集合继承体系:

      |--ArrayList

      |--LinkedList

      |--Vector

      List本身是Collection接口的子接口,具备了Collection的所有方法。现在学习List体系特有的共性方法,查阅方法发现List的特有方法都有索引,这是该集合最大的特点。

    凡是可以操作角标的方法都是该体系特有的方法。

    1、List集合特有的方法

    (1)、添加

    1 void  add(int index,E element);//在指定索引位置上添加元素
    2 void  addAll(int index,Collection<? extends E> c);//在指定索引位置上添加一堆元素

     (2)、删除

    1 Object  remove(int index);//删除指定索引位置上的元素

     (3)、修改

    1 Object  set(int index, E  element);//对指定索引位进行元素的修改

     (4)、获取

    1 Object  get(int index);//获取指定索引位置上的元素
    2 int  indexOf(Object obj);//获取指定元素第一次出现的索引位,如果该元素不存在返回-1;所以通过-1,可以判断一个元素是否存在。
    3 int  lastIndexOf(Object obj);//反向索引指定元素的位置。
    4 List  subList(int from,int to);//获取子列表,包含头不包含尾
    5 Iterator  listIterator();//List集合特有的迭代器
    6 Iterator  listIterator(int index);//从列表的指定位置开始返回List集合迭代器

     注意:对于List集合,底层判断元素是否相同,其实用的是元素自身的equals方法完成的。所以建议元素都要复写equals方法,建立元素对象自己的比较相同的条件依据。

    代码演示:

     1 import java.util.*;
     2 class ListDemo 
     3 {
     4     public static void main(String[] args) 
     5     {
     6         List<String> list=new ArrayList<String>();
     7         list.add("黑马");
     8         list.add("安卓");
     9         list.add("小明");
    10         list.add("王武");
    11         list.add("安卓");
    12         System.out.println("list:"+list);
    13         //在指定位置上添加元素
    14         list.add(3,"我爱黑马");
    15         System.out.println("listadd:"+list);
    16 
    17         //删除指定位置上的元素
    18         list.remove(4);
    19         System.out.println("listremove:"+list);
    20 
    21         //设置元素        
    22         System.out.println("listset:"+list.set(2,"我爱安卓"));
    23 
    24         //获取指定位置上的元素
    25         System.out.println("listget"+list.get(2));
    26 
    27         //获取元素第一次出现的位置。
    28         System.out.println("indexOf="+list.indexOf("安卓"));
    29 
    30         //获取子列表,包含头不包含尾
    31         System.out.println(list.subList(2,4));
    32     }
    33     
    34 }

     2、List集合元素取出方式

    (1)、List集合第一种取出方式:因为List集合有索引(角标)这个特殊的原因,所以List集合有自己特有的迭代方式,get方法。 

     1 import java.util.*;
     2 class ListIteratorDemo 
     3 {
     4     public static void main(String[] args) 
     5     {
     6         List<String> list=new ArrayList<String>();
     7         list.add("黑马");
     8         list.add("安卓");
     9         list.add(".NET");
    10         list.add("IOS");
    11         //用集合的长度做循环条件,get方法取出元素
    12         for (int x=0;x<list.size() ;x++ )
    13         {            
    14             System.out.println(list.get(x));
    15         }
    16     }
    17 }

    (2)、List集合第二种取出方式:用Collection集合中的iterator()方法,这种方法有弊端只能遍历的过程中对集合删除操作。

     1 import java.util.*;
     2 class ListIteratorDemo 
     3 {
     4     public static void main(String[] args) 
     5     {
     6         List<String> list=new ArrayList<String>();
     7         list.add("黑马");
     8         list.add("安卓");
     9         list.add(".NET");
    10         list.add("IOS");
    11         //Collection接口中的iterator方法。
    12         for (Iterator<String> it=list.iterator();it.hasNext() ; )
    13         {
    14             String s=it.next();
    15             if(s.equals("IOS")){
    16 //                list.add("JAVA");//ConcurrentModificationException异常,出现并发操作。
    17                 it.remove();//将IOS的引用从集合中删除了
    18             }
    19             System.out.println(s);
    20         }
    21 
    22     }
    23 }

      在迭代时,不可以通过集合对象的方法操作集合中的元素。因为会发生ConcurrentModificationException异常。Iterator方法是有限的,只能对元素进行判断,取出,删除的操作。那么如果想要其他的操作如添加,修改等,该怎么办呢?这时候就需要使用其子接口ListIterator,该接口只能通过List集合的ListIterator方法获取。

    (3)、List集合取出方式第三种方式:Lsit集合特有迭代器:ListIterator

    ListIterator迭代器中的方法:

     1 import java.util.*;
     2 class ListIteratorDemo 
     3 {
     4     public static void main(String[] args) 
     5     {
     6         List<String> list=new ArrayList<String>();
     7         list.add("黑马");
     8         list.add("安卓");
     9         list.add(".NET");
    10         list.add("IOS");
    11         //获取ListIterator迭代器对象
    12         for (ListIterator<String> li=list.listIterator();li.hasNext() ; )
    13         {
    14             //它可以实现在迭代过程中完成对元素的增删改查。
    15             //注意:只有list集合具备该迭代功能。
    16             String s=li.next();
    17             if(s.equals("IOS"))
    18                 li.add("JAVA");//增加元素
    19             if(s.equals(".NET"))
    20                 li.remove();//删除元素
    21             if(s.equals("安卓"))
    22                 li.set("JAVAEE");//修改元素
    23         }
    24         System.out.println(list);
    25 
    26     }
    27 }

    五、ArrayList、LinkedList、Vector集合

    1、ArrayList集合的方法和List集合的方法差不多一样。所以可参照List的方法。

    2、LinkedList集合

    LinkedList集合中特有的方法:

    (1)、添加元素

    1 addFirst();//将指定元素插入集合元素的开头
    2 addLast();//将指定元素插入集合元素的末尾

     ------JDK1.6版本后新的方法----------------

    1 offerFirst();//与addFirst方法没有区别
    2 offerLast();//与addLast方法没有区别

     (2)、获取但不删除元素 

    1 //获取但不删相互,如果链表为空,抛出NoSuchElementException
    2 E  getFirst();//返回此集合的第一个元素
    3 E  getLast();//返回此集合的最后一个元素

      ------JDK1.6版本后新的方法----------------

    1 //获取但不移除,如果链表为空,返回null。
    2 peekFirst();
    3 peekLast();

     (3)、获取并删除元素

    1 //获取并移除,如果链表为空,抛出NoSuchElementException。
    2 E   removeFirst();//移除并返回此集合的第一个元素
    3 E   removeLast();//移除并返回此集合的最后一个元素

        ------JDK1.6版本后新的方法----------------

    1 //获取并移除,如果链表为空,返回null;
    2 pollFirst();
    3 pollLast();

      因为LinkedList中有特有的方法removeFirst()或者removeLast()(pollFirst、pollLast),所以LinkedList有4种迭代的方法。一种是:Iterator,一种是:iterator,一种是for循环遍历get方法,一种是LinkedList特有的方法。

     1 //LinkedList特有取出方式
     2 import java.util.*;
     3 class LinkedListDemo 
     4 {
     5     public static void main(String[] args) 
     6     {
     7         LinkedList<String> list=new LinkedList<String>();
     8         list.add("黑马");
     9         list.add("安卓");
    10         list.add(".NET");
    11         list.add("IOS");
    12         while(!(list.isEmpty()))//通过判断集合是否为空来循环删除元素,知道为空停止循环
    13             System.out.println(list.removeFirst());    //获取元素并且删除元素    
    14     }
    15 }

    3、Vector集合

    (1)、Vector中特有的方法

    枚举就是Vector特有的取出方式。发现枚举和迭代器很像。其实枚举和迭代是一样的。因为枚举的名称以及方法的名称都过长。所以被迭代器取代了。

    1 //获取枚举接口的方法
    2 Enumeration<E>   elements();//返回此集合的枚举

     而Eumeration枚举接口中的方法:

    1 boolean  hasMoreElements();//相当于Iterator中的hasNext()
    2 E  nextElement();//相当与Iterator中的next()

     另外Collections集合工具类中也提供了Collection集合获取枚举接口的方法

    1  static Enumeration< T>   enumeratio(Collection<T> c);//返回一个指定 collection 上的枚举。

     代码演示:

     1 import java.util.*;
     2 class VectorDemo 
     3 {
     4     public static void main(String[] args) 
     5     {
     6         Vector<String> v=new Vector<String>();
     7         v.add("黑马");
     8         v.add("安卓");
     9         v.add("IOS");
    10         v.add("JAVAEE");
    11 
    12         //用Iterator迭代器方法取出元素
    13         for (Iterator<String> it=v.iterator();it.hasNext() ; )
    14         {
    15             System.out.println(it.next());
    16         }
    17 
    18         //用Enumeration枚举的方法取出元素
    19         for (Enumeration<String> en=v.elements();en.hasMoreElements() ; )
    20         {
    21             System.out.println(en.nextElement());
    22         }
    23 
    24         //Collections.enumeration()方法获取枚举Enumeration接口
    25         for (Enumeration<String> en=Collections.enumeration(v);en.hasMoreElements() ; )
    26         {
    27             System.out.println(en.nextElement());
    28         }
    29     }
    30 }

      4、List集合综合练习

    (1)、请使用LinkedList来模拟一个堆栈或者队列数据结构。

      堆栈:先进后出 First In Last Out FILO
      队列:先进先出 First In First Out FIFO

    思路:应该自定义一个LinkedList类,把要LinkedList封装到自己的类中。

     1 import java.util.*;
     2 class DuiLie
     3 {
     4     private LinkedList link;
     5     //对象一初始化就创建了LinkedList集合
     6     DuiLie(){
     7         link=new LinkedList();
     8     }
     9     //队列的添加元素的功能。
    10     public void myAdd(Object obj){
    11         link.addFirst(obj);
    12     }
    13     //队列的删除元素的功能。
    14     public Object myRemove(){
    15         return link.removeLast();
    16     }
    17     //判断队列是否为空
    18     public boolean isNull(){
    19         return link.isEmpty();
    20     }
    21 
    22 }
    23 class DuiLieDemo
    24 {
    25     public static void main(String[] args) 
    26     {
    27         DuiLie dl=new DuiLie();
    28         dl.myAdd("黑马");
    29         dl.myAdd("IOS");
    30         dl.myAdd("安卓");
    31         dl.myAdd(".NET");
    32         dl.myAdd("JAVAEE");
    33         while (!(dl.isNull()))
    34         {
    35             System.out.println(dl.myRemove());
    36         }
    37 
    38     }
    39 }

     (2)、将自定义对象作为元素存到ArrayList集合中,并去除重复元素。比如:存人对象,同姓名同年龄,视为同一个人。为重复元素。

     1 /*
     2 List集合中必须定义一个新的容器来过滤重复元素.
     3 而set集合则不用,因为set集合是无序的,不可重复的。
     4 */
     5 import java.util.*;
     6 class Person
     7 {
     8     private String name;
     9     private int age;
    10     Person(String name,int age)
    11     {
    12         this.name=name;
    13         this.age=age;
    14     }
    15     public void setName(String name){
    16         this.name=name;
    17     }
    18     public String getName(){
    19         return name;
    20     }
    21     public void setAge(int age){
    22         this.age=age;
    23     }
    24     public int getAge(){
    25         return age;
    26     }
    27     public String toString(){
    28         return "name="+name+"....."+"age="+age;
    29     }
    30     public boolean equals(Object obj){//即使使用了泛型,equals方法中的参数也是Object obj,
    31         if(!(obj instanceof Person))//因为复写的Object类中的方法,Object类的equals方法参数就是Object obj。
    32             throw new RuntimeException("类型转换异常");
    33         Person p=(Person)obj;
    34         return this.name.equals(p.name)&&this.age==p.age;//判断name和age是否相同
    35     }
    36 }
    37 class ArrayListDemo
    38 {
    39     public static void main(String[] args) 
    40     {
    41         List<Person> list=new ArrayList<Person>();
    42         list.add(new Person("黑马",120));
    43         list.add(new Person("安卓",110));
    44         list.add(new Person("IOS",45));
    45         list.add(new Person(".NET",97));
    46         list.add(new Person("JVAEE",12));
    47         list.add(new Person("IOS",45));
    48         list.add(new Person("黑马",120));
    49         //迭代原集合
    50         printCollection(list);        
    51         System.out.println("---去除重复元素后的集合---------");
    52         list=getSingleElement(list);
    53         printCollection(list);
    54 
    55     }
    56     public static List<Person> getSingleElement(List<Person> list){
    57         //1、定义一个临时容器用来装过滤后的数据
    58         List<Person> newList=new ArrayList<Person>();
    59         //2、迭代list集合
    60         for (Iterator<Person> it=list.iterator();it.hasNext() ;)
    61         {
    62             Person p=it.next();
    63         //3、判断被迭代到的元素是否在临时容器存在
    64         //contains方法内部依靠的是equals方法,其实remove方法也调用equals方法的   
    65             if(!(newList.contains(p)))
    66                 newList.add(p);
    67         }
    68         return newList;
    69 
    70     }
    71     //迭代器取出集合中的元素
    72     private static void printCollection(List<Person> list){
    73         for (Iterator<Person> it=list.iterator();it.hasNext() ; )
    74         {
    75             System.out.println(it.next());
    76         }
    77     }
    78 }

    六、Set<E>集合(只能用Iterator迭代器取数据)

    Set接口中的方法和Collection中方法一致的。Set集合元素不可重复且无序。Set接口取出方式只有一种:迭代器。

    Set集合继承体系

      |--HashSet

        |--LinkedHashSet

      |--TreeSet

     1 import java.util.*;
     2 class  SetDemo
     3 {
     4     public static void main(String[] args) 
     5     {
     6         //Set集合无需并且不可重复,方法和Collection方法一样
     7         Set<String> set=new HashSet<String>();
     8         set.add("黑马");//添加元素
     9         set.add("JAVAEE");
    10         set.add("安卓");
    11         set.add("IOS");
    12         set.add(".NET");
    13         set.add("JAVAEE");
    14         set.remove("IOS");//删除元素
    15 
    16         //Iterator迭代器取出元素
    17         for (Iterator<String> it=set.iterator();it.hasNext() ; )
    18         {
    19             System.out.println(it.next());
    20         }
    21     }
    22 }

     七、HashSet、LinkedHashSet、TreeSet集合

    (1)、HashSet集合

    HashSet实现Set接口,由哈希表(实际上是一个HashMap实例)支持。

    哈希表确定元素是否相同:因为集合本身不可重复的特点所以不用定义新的Set集合来存放不重复元素。
    (1)、 先判断的是两个元素的哈希值是否相同。如果相同,再判断两个对象的内容是否相同。

    (2)、 判断哈希值相同,其实判断的是对象的HashCode方法。判断内容相同,用的是equals方法。如果哈希值不同,不需要判断equals。

    判断HastSet集合中的元素是否相同,一般要复写对象的hashCode方法和equals方法。

    哈希表的原理:

    (1)、对对象元素中的关键字(对象中的特有数据),进行哈希算法的运算,并得出一个具体的算法值,这个值 称为哈希值。

    (2)、哈希值就是这个元素的位置。

    (3)、如果哈希值出现冲突,再次判断这个关键字对应的对象是否相同。如果对象相同,就不存储,因为元素重复。如果对象不同,就存储,在原来对象的哈希值基础 +1顺延。

    (4)、存储哈希值的结构,我们称为哈希表。

    (5)、既然哈希表是根据哈希值存储的,为了提高效率,最好保证对象的关键字是唯一的。 这样可以尽量少的判断关键字对应的对象是否相同,提高了哈希表的操作效率。

    需求:往HashSet集合中存储Person对象。如果姓名和年龄相同,视为同一个人,视为相同元素。 

     1 /*
     2 如果姓名和年龄相同,视为同一个人,视为相同元素
     3 */
     4 
     5 import java.util.*;
     6 class Person
     7 {
     8     private String name;
     9     private int age;
    10     Person(String name,int age)
    11     {
    12         this.name=name;
    13         this.age=age;
    14     }
    15     public void setName(String name){
    16         this.name=name;
    17     }
    18     public String getName(){
    19         return name;
    20     }
    21     public void setAge(int age){
    22         this.age=age;
    23     }
    24     public int getAge(){
    25         return age;
    26     }
    27     public String toString(){
    28         return "name="+name+"....."+"age="+age;
    29     }
    30     public int hashCode(){//复写了hashCode方法
    31         return name.hashCode()+age*37;
    32     }
    33     public boolean equals(Object obj){//即使使用了泛型,equals方法中的参数也是Object obj,
    34         if(!(obj instanceof Person))//因为复写的Object类中的方法,Object类的equals方法参数就是Object obj。
    35             throw new RuntimeException("类型转换异常");
    36         Person p=(Person)obj;
    37         return this.name.equals(p.name)&&this.age==p.age;//建立了自己的比较方式
    38     }
    39 }
    40 class HashSetDemo
    41 {
    42     public static void main(String[] args) 
    43     {
    44         Set<Person> set=new HashSet<Person>();
    45         set.add(new Person("黑马",98));
    46         set.add(new Person("安卓",76));
    47         set.add(new Person("IOS",67));
    48         set.add(new Person(".NET",34));
    49         set.add(new Person("JAVAEE",21));
    50         set.add(new Person("IOS",67));
    51         set.add(new Person("安卓",76));
    52         for (Iterator<Person> it=set.iterator();it.hasNext() ; )
    53         {
    54             System.out.println(it.next());
    55         }
    56     }
    57 }

     2、LinkedHashSet集合

    LinkedHashSet这个集合不仅存入的顺序和取出的顺序一致,并且该集合可以自动去除重复元素。

    需求:数组去重复,例如: 原始数组是{4,2,4,6,1,2,4,7,8},得到结果{4,2,6,1,7,8}

     1 import java.util.*;
     2 class LinkedHashSetDemo
     3 {
     4     public static void main(String[] args) 
     5     {
     6         int[] arr={4,2,4,6,1,2,4,7,8};
     7         Integer[] in=getSingleElement(arr);
     8         for (int x=0;x<in.length ;x++ )
     9         {
    10             if(x<in.length-1)
    11                 System.out.print(in[x]+",");
    12             else
    13                 System.out.print(in[x]);
    14         }
    15 
    16     }
    17     public static Integer[] getSingleElement(int[] arr){
    18         //无序变有序,并且去重
    19         LinkedHashSet<Integer> lhs=new LinkedHashSet<Integer>();
    20         for (int x=0;x<arr.length ;x++ )
    21         {
    22             lhs.add(arr[x]);
    23         }
    24         //集合变成数组返回
    25         return (Integer[])lhs.toArray(new Integer[lhs.size()]);
    26     }
    27 }

     3、TreeSet集合

    用于对Set集合进行元素的指定顺序排序,排序需要依据元素自身具备的比较性。 如果元素不具备比较性,在运行时会发生ClassCastException异常。

    TreeSet判断元素唯一性的方式:就是根据比较方法的返回结果是否为0,是0就是相同元素,不存。

    TreeSet集合排序的两种方式:

    (1)、TreeSet排序的第一种方式:让元素自身具备比较性。元素需要实现Comparable接口,覆盖compareTo(T)方法。也种方式也成为元素的自然顺序,或者叫做默认顺序。

    (2)、TreeSet的第二种排序方式:让集合具备比较性。当元素自身不具备比较性时,或者具备的比较性不是所需要的。这时就需要让集合自身具备比较性。在集合初始化时,就有了比较方式。集合需要传入比较器(Comparator接口),让集合具备比较行为。定义一个Comparator的子类对象,复写compare(T o1, T o2)方法。 将该类对象作为参数传递给TreeSet集合的构造函数。如果自定义类实现了Comparable接口,并且TreeSet的构造函数中也传入了比较器,那么将以比较器的比较规则为准。记住,排序时,当主要条件相同时,一定判断一下次要条件。Comparable<T>、Comparator<T>都带着泛型的。第二种方式较为灵活。

    注:只有TreeSet和TreeMap集合的构造函数能接收Comparator比较器。

    需求:往TreeSet集合中存储Student对象,并按照学生的姓名排序。

    第一种方式:让学生自身具备比较性,实现Comparable接口,复写compareTo方法

     1 import java.util.*;
     2 class Student implements Comparable<Student>
     3 {
     4     private String name;
     5     private int age;
     6     Student(String name,int age){
     7         this.name=name;
     8         this.age=age;
     9     }
    10     public void setName(String name){
    11         this.name=name;
    12     }
    13     public String getName(){
    14         return name;
    15     }
    16     public void setAge(int age){
    17         this.age=age;
    18     }
    19     public int getAge(){
    20         return age;
    21     }
    22     public String toString(){
    23         return "name="+name+"....."+"age="+age;
    24     }
    25     //复写Comparable接口的compareTo方法
    26     public int compareTo(Student stu){
    27         int num=this.name.compareTo(stu.name);//先按照姓名排序,如果姓名相同然后再按照年龄排序
    28         if(num==0)
    29             return new Integer(this.age).compareTo(new Integer(stu.age));//按照年龄排序
    30         return num;
    31     }
    32 }
    33 class TreeSetDemo 
    34 {
    35     public static void main(String[] args) 
    36     {
    37         Set<Student> set=new TreeSet<Student>();
    38         set.add(new Student("黑马",120));
    39         set.add(new Student("安卓",43));
    40         set.add(new Student("IOS",87));
    41         set.add(new Student(".NET",21));
    42         set.add(new Student("JAVAEE",12));
    43         set.add(new Student("PHP",98));
    44         set.add(new Student("黑马",34));
    45         for (Iterator<Student> it=set.iterator();it.hasNext() ; )
    46         {
    47             System.out.println(it.next());
    48         }
    49     }
    50 }

     第二种方式:学生自身不具备比较性,这时候就可以定义一个类实现Comparator接口,覆盖compare(T o1, T o2)方法。

     1 //Student类接上例
     2 //实现Comparator接口,复写compare方法。比较器
     3 class StuComparator implements Comparator<Student>
     4 {
     5     public int compare(Student s1,Student s2){
     6         int num=s1.getAge()-s2.getAge();//先按照年龄排序
     7         if(num==0)
     8             return s1.getName().compareTo(s2.getName());//年龄相同的再按照姓名排序
     9         return num;
    10     }
    11 }
    12 class TreeSetDemo 
    13 {
    14     public static void main(String[] args) 
    15     {
    16         Set<Student> set=new TreeSet<Student>(new StuComparator());//两种方式同时存在以比较器为主
    17         set.add(new Student("黑马",120));
    18         set.add(new Student("安卓",43));
    19         set.add(new Student("IOS",87));
    20         set.add(new Student(".NET",21));
    21         set.add(new Student("JAVAEE",12));
    22         set.add(new Student("PHP",98));
    23         set.add(new Student("黑马",34));
    24         for (Iterator<Student> it=set.iterator();it.hasNext() ; )
    25         {
    26             System.out.println(it.next());
    27         }
    28     }
    29 }

     练习:对字符串进行长度排序。

     1 import java.util.*;
     2 class LenComparator implements Comparator<String>
     3 {
     4     public int compare(String s1,String s2){
     5         int num=s1.length()-s2.length();//按照长度排序
     6         return (num==0)?s1.compareTo(s2):num;//如果长度相同,按照字符串自然排序
     7     }
     8 }
     9 class StringLength 
    10 {
    11     public static void main(String[] args) 
    12     {
    13         TreeSet<String> ts=new TreeSet<String>(new LenComparator());
    14         ts.add("aaaa");
    15         ts.add("zz");
    16         ts.add("nbag");
    17         ts.add("cba");
    18         ts.add("abc");        
    19         for (Iterator it=ts.iterator();it.hasNext() ; )
    20         {
    21             System.out.println(it.next());
    22         }
    23 
    24     }
    25 }

    八、Map<K,V>接口

    Map集合该集合存储键值对。一对一对往里存。而且要保证键的唯一性。Map也称为双列集合;Collection集合称为单列集合,Collection一次存一个元素。和Set很像,Set底层就是使用了Map集合。

    Map集合继承体系:

      |--Hashable

        |--Properties

      |--HashMap

        |--LinkedHashMap

      |--TreeMap

    1、Map集合常用方法

    (1)、添加元素

    1 Value  put(key,value);//返回前一个和key关联的值,如果没有返回null。如果出现添加相同的键,那么后添加的值会覆盖原有键对应的值,并且put方法会返回被覆盖的值

     (2)、删除

    1 void  clear();//清空map集合
    2 value  remove(Object key);//根据指定的key删除这个键值对

     (3)、判断

    1 boolean  containsKey(key);//判断集合中是否存在指定的键
    2 boolean  containsValue(value);//判断集合中是否存在指定的值
    3 boolean  isEmpty();//判断集合是否为null

     (4)、获取

    1 value  get(Key);//通过键获取值,如果没有该键返回null,可以通过返回null来判断是否存在指定键。当然有特殊情况,就是在hashmap集合中,是可以存储null键null值的。
    2 int  size();//获取键值对个数,也就是Map集合的长度
    3 Set<Key>  keySet();//返回Set集合,该集合中存放的是Map集合中的全部键(Key)的值
    4 Set<Map.Entry<Key,Value>>  entrySet();//返回Set集合,该集合存放的是Map集合的映射关系,关系的数据类型就是:Map.Entry。
    5 Collection<Value>   values();//返回Collection集合,该集合中存放的是Map集合中的全部值。返回的Collection集合可以通过Iterator迭代器获取到全部值

     map中是没有迭代器的,collection具备迭代器,只要将map集合转成Set集合,可以使用迭代器了。之所以转成set,是因为map集合具备着键的唯一性,其实set集合就来自于map,set集合底层其实用的就是map的方法。

    2、 Map集合的三种取出方式

    (1)、取出map集合中所有元素的方式一:  Set<Key>  keySet()方法。

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

     1 import java.util.*;
     2 class KeySetDemo 
     3 {
     4     public static void main(String[] args) 
     5     {
     6         Map<Integer,String> map=new HashMap<Integer,String>();
     7         map.put(1,"王武");
     8         map.put(7,"孙琦");
     9         map.put(6,"李四");
    10         map.put(4,"赵四");
    11         map.put(2,"钱枫");
    12         //先获取map集合的所有键的Set集合,keySet();
    13         Set<Integer> keyset=map.keySet();
    14         //有了Set集合。就可以获取其迭代器。
    15         for (Iterator<Integer> it=keyset.iterator();it.hasNext() ; )
    16         {
    17             Integer key=it.next();
    18             //有了键可以通过map集合的get方法获取其对应的值。
    19             String value=map.get(key);
    20             System.out.println("key="+key+":::"+"value="+value);
    21         }
    22     }
    23 }

     (2)、取出map集合中所有元素的方式二:Set<Map.Entry<Key,Value>>  entrySet()方法。

    将map集合中的映射关系存入到了set集合中,而这个关系的数据类型就是:Map.Entry. Map.Entry 其实Entry也是一个接口,它是Map接口中的一个内部接口。为什么要定义在内部呢?

    因为只有有了Map集合,有了键值对,才会有键值的映射关系。关系属于Map集合中的一个内部事物。而且该事物在直接访问Map集合中的元素。

    接口 Map.Entry<K,V>中的方法:

     1 import java.util.*;
     2 class EntrySetDemo 
     3 {
     4     public static void main(String[] args) 
     5     {
     6         Map<Integer,String> map=new HashMap<Integer,String>();
     7         map.put(1,"王武");
     8         map.put(7,"孙琦");
     9         map.put(6,"李四");
    10         map.put(4,"赵四");
    11         map.put(2,"钱枫");
    12         //将Map集合中的映射关系(Map.Entry)取出。存入到Set集合中。
    13         Set<Map.Entry<Integer,String>> entryset=map.entrySet();
    14         //用迭代器进行迭代Set集合
    15         for (Iterator<Map.Entry<Integer,String>> it=entryset.iterator();it.hasNext() ; )
    16         {
    17             //it.next()返回的是Map集合中的映射关系(Map.Entry<K,V>)
    18             Map.Entry<Integer,String> en=it.next();
    19             //通过Map.Entry中的getKey()和getValue()取到Map集合键和值。
    20             int key=en.getKey();
    21             String value=en.getValue();
    22             System.out.println("key="+key+":::"+"value="+value);
    23         }
    24     }
    25 }

      (3)、取出map集合中所有元素的方式三:Collection<Value>  values();返回Collection集合,然后在用Iterator迭代器来取出元素

     1 import java.util.*;
     2 class ValuesDemo 
     3 {
     4     public static void main(String[] args) 
     5     {
     6         Map<Integer,String> map=new HashMap<Integer,String>();
     7         map.put(1,"王武");
     8         map.put(7,"孙琦");
     9         map.put(6,"李四");
    10         map.put(4,"赵四");
    11         map.put(2,"钱枫");
    12         //用values方法取到Map集合中的全部的值,存放到Collection中
    13         Collection<String> value=map.values();
    14         //用迭代器进行迭代这个存放Map集合全部值的Collection集合
    15         for (Iterator<String> it=value.iterator();it.hasNext() ; )
    16         {
    17             System.out.println("value="+it.next());
    18         }
    19     }
    20 }

     3、Map集合综合练习

    (1)、需求:描述一个学生,学生属性:姓名,年龄。每一个学生都有对应的归属地。学生Student,地址String。注意:姓名和年龄相同的视为同一个学生。保证学生的唯一性。

     1 import java.util.*;
     2 class Student 
     3 {
     4     private String name;
     5     private int age;
     6     Student(String name,int age){
     7         this.name=name;
     8         this.age=age;
     9     }
    10     public void setName(String name){
    11         this.name=name;
    12     }
    13     public void setAge(int age){
    14         this.age=age;
    15     }
    16     public String getName(){
    17         return name;
    18     }
    19     public int getAge(){
    20         return age;
    21     }
    22     public String toString(){
    23         return "name="+name+"....."+"age="+age;
    24     }
    25     public int hashCode(){
    26         return name.hashCode()+age*37;
    27     }
    28     public boolean equals(Object obj){
    29         if(!(obj instanceof Student))
    30             throw new RuntimeException("类型转换异常");
    31         Student stu=(Student)obj;
    32         return this.name.equals(stu.name)&&this.age==stu.age;
    33     }
    34 }
    35 class HashMapDemo
    36 {
    37     public static void main(String[] args) 
    38     {
    39         //将学生对象和学生的归属地通过键与值的形式存储到map集合中
    40         Map<Student,String> map=new HashMap<Student,String>();
    41         map.put(new Student("张三",20),"北京");
    42         map.put(new Student("钱枫",21),"深圳");
    43         map.put(new Student("王武",19),"郑州");
    44         map.put(new Student("赵四",33),"香港");
    45         map.put(new Student("孙琦",29),"广州");
    46         map.put(new Student("钱枫",21),"上海");
    47         //第一种方式:keySet();
    48         for (Iterator<Student> it=map.keySet().iterator();it.hasNext() ; )
    49         {
    50             Student stu=it.next();
    51             String address=map.get(stu);
    52             System.out.println(stu+":::"+address);
    53         }
    54         //第二种取出方式
    55         for (Iterator<Map.Entry<Student,String>> it=map.entrySet().iterator();it.hasNext() ; )
    56         {
    57             Map.Entry<Student,String> me=it.next();
    58             Student stu=me.getKey();
    59             String address=me.getValue();
    60             System.out.println(stu+":::"+address);
    61         }
    62     }
    63 }

     (2)、需求:对学生对象的年龄进行升序排序。因为数据是以键值对形式存在的。所以要使用可以排序的Map集合中TreeMap集合。

     1 import java.util.*;
     2 class Student implements Comparable<Student>
     3 {
     4     private String name;
     5     private int age;
     6     Student(String name,int age){
     7         this.name=name;
     8         this.age=age;
     9     }
    10     public void setName(String name){
    11         this.name=name;
    12     }
    13     public void setAge(int age){
    14         this.age=age;
    15     }
    16     public String getName(){
    17         return name;
    18     }
    19     public int getAge(){
    20         return age;
    21     }
    22     public String toString(){
    23         return "name="+name+"....."+"age="+age;
    24     }
    25     public int compareTo(Student stu){
    26         int num=this.age-stu.age;//按年龄排序
    27         if(num==0)
    28             return this.name.compareTo(stu.name);//按姓名排序
    29         return num;
    30     }
    31     /*
    32     因为写的Student类,使用者有可能存放到HashMap集合中。
    33     所以有必要复写hashCode方法和equals方法。
    34     而且即使你不写,这两个方法都会存在Student类中,因为Object类中有这两个方法
    35     public int hashCode(){
    36         return name.hashCode()+age*37;
    37     }
    38     public boolean equals(Object obj){
    39         if(!(obj instanceof Student))
    40             throw new RuntimeException("类型转换异常");
    41         Student stu=(Student)obj;
    42         return this.name.equals(stu.name)&&this.age==stu.age;
    43     }
    44     */
    45 }
    46 class StuComparator implements Comparator<Student>
    47 {
    48     public int compare(Student s1,Student s2){
    49         int num=s1.getAge()-s2.getAge();
    50         return (num==0)?s1.getName().compareTo(s2.getName()):num;
    51     }
    52 }
    53 class TreeMapDemo 
    54 {
    55     public static void main(String[] args) 
    56     {
    57         TreeMap<Student,String> tm=new TreeMap<Student,String>(new StuComparator());
    58         tm.put(new Student("张三",20),"北京");
    59         tm.put(new Student("钱枫",21),"深圳");
    60         tm.put(new Student("王武",19),"郑州");
    61         tm.put(new Student("赵四",33),"香港");
    62         tm.put(new Student("孙琦",29),"广州");
    63         tm.put(new Student("钱枫",21),"武汉");
    64         tm.put(new Student("王武",19),"上海");//键相同值就会覆盖原来的键的值
    65         Set<Map.Entry<Student,String>> entryset=tm.entrySet();
    66         for (Iterator<Map.Entry<Student,String>> it=entryset.iterator();it.hasNext() ; )
    67         {
    68             Map.Entry<Student,String> en=it.next();
    69             Student stu=en.getKey();
    70             String address=en.getValue();
    71             System.out.println(stu+":::"+address);
    72         }
    73     }
    74 }

     (3)、需求: 使用LinkedHashMap则是跟原来存入的顺序是一致的。

     1 import java.util.*;
     2 class LinkedHashMapDemo 
     3 {
     4     public static void main(String[] args) 
     5     {
     6         LinkedHashMap<Integer,String> lhm=new LinkedHashMap<Integer,String>();
     7         lhm.put(1,"王武");
     8         lhm.put(7,"孙琦");
     9         lhm.put(6,"李四");
    10         lhm.put(4,"赵四");
    11         lhm.put(2,"钱枫");
    12         lhm.put(2,"黑马");//覆盖原来相同键的值
    13         Set<Map.Entry<Integer,String>> entryset=lhm.entrySet();
    14         for (Iterator<Map.Entry<Integer,String>> it=entryset.iterator();it.hasNext() ; )
    15         {
    16             Map.Entry<Integer,String> en=it.next();
    17             Integer key=en.getKey();
    18             String value=en.getValue();
    19             System.out.println(key+":::"+value);
    20         }
    21     }
    22 }

     运行结果:

     (4)、需求:"sdfgzxcvas--==,.?dfxcvdf"获取该字符串中的字母出现的次数。希望打印结果:a(1)c(2).....

    通过结果发现,每一个字母都有对应的次数。说明字母和次数之间都有映射关系。注意了,当发现有映射关系时,可以选择Map集合。因为Map集合中存放就是映射关系。

    什么使用Map集合呢?

    当数据之间存在这映射关系时,就要先想Map集合。

    思路:

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

    2,定义一个Map集合,因为打印结果的字母有顺序,所以使用Treemap集合。

    3,遍历字符数组。将每一个字母作为键去查Map集合。如果返回null,将该字母和1存入到Map集合中。

        如果返回不是null,说明该字母在Map集合已经存在并有对应次数。     那么就获取该次数并进行自增,然后将该字母和自增后的次数存入到Map集合中。覆盖掉原来键所对应的值。

    4,将Map集合中的数据变成指定的字符串形式返回。

     1 //"sdfgzxcvas--==,.?dfxcvdf"获取该字符串中的字母出现的次数。希望打印结果:a(1)c(2).....
     2 import java.util.*;
     3 class  TreeMapTest
     4 {
     5     public static void main(String[] args) 
     6     {
     7         String str="sdfgzxcvas--==,.?dfxcvdf";
     8         str=getCharCount(str);
     9         System.out.println(str);
    10     }
    11     public static String getCharCount(String str){
    12         TreeMap<Character,Integer> tm=new TreeMap<Character,Integer>();
    13         //把字符串转换成字符数组
    14         char[] arr=str.toCharArray();        
    15         for (int x=0;x<arr.length ;x++ )
    16         {
    17             //程序健壮性的判断,如果是除了字母以外的字符直接过滤掉
    18             if(!((arr[x]>='a'&& arr[x]>='z') || (arr[x]>='A'&& arr[x]>='Z')))
    19                 continue;
    20             //将数组中的字母作为键去查map表中的值
    21             Integer value=tm.get(arr[x]);
    22             int count=0;
    23             //判断值是否为null,如果不为空记录这个值
    24             if(value!=null)
    25                 count=value;
    26             //如果不为空,count加1存进集合中,如果count=0,也加1存进去
    27             count++;
    28             tm.put(arr[x],count);            
    29             /*
    30             if(value==null)
    31                 tm.put(arr[x],1);
    32             else{
    33                 value=value+1;
    34                 tm.put(arr[x],value);
    35             }
    36             */
    37         }
    38         //创建字符串缓冲区用来修改成固定的字符串格式。
    39         StringBuilder sb=new StringBuilder();
    40         for (Iterator<Map.Entry<Character,Integer>> it=tm.entrySet().iterator();it.hasNext() ; )
    41         {
    42             Map.Entry<Character,Integer> en=it.next();
    43             Character key=en.getKey();
    44             Integer value=en.getValue();
    45             sb.append(key+"("+value+")");
    46         }        
    47         return sb.toString();
    48     }
    49 }

     (5)、Map集合扩展

      在很多项目中,应用比较多的是一对多的映射关系,这就可以通过嵌套的形式将多个映射定义到一个大的集合中,并将大的集合分级处理,形成一个体系。

     1 import java.util.*;
     2 class Student
     3 {
     4     private String id;
     5     private String name;
     6     Student(String id,String name)
     7     {
     8         this.id = id;
     9         this.name = name;
    10     }
    11     public String toString()
    12     {
    13         return id+":::"+name;
    14     }
    15 }
    16 class  MapDemo3
    17 {
    18     public static void demo()
    19     {
    20         HashMap<String,List<Student>> czbk = new HashMap<String,List<Student>>();
    21         List<Student> reyu = new ArrayList<Student>();
    22         List<Student> jiuye = new ArrayList<Student>();
    23         czbk.put("yureban",reyu);
    24         czbk.put("jiuyeban",jiuye);
    25         reyu.add(new Student("01","zhagnsa"));
    26         reyu.add(new Student("04","wangwu"));
    27         jiuye.add(new Student("01","zhouqi"));
    28         jiuye.add(new Student("02","zhaoli"));
    29         Iterator<String> it = czbk.keySet().iterator();
    30         while(it.hasNext())
    31         {
    32             String roomName = it.next();
    33             List<Student> room = czbk.get(roomName);            
    34             System.out.println(roomName);
    35             getInfos(room);
    36         }    
    37     }
    38     public static void getInfos(List<Student> list)
    39     {
    40         Iterator<Student> it = list.iterator();
    41         while(it.hasNext())
    42         {
    43             Student s = it.next();
    44             System.out.println(s);
    45         }
    46     }
    47     public static void main(String[] args) 
    48     {
    49          demo();        
    50     }
    51     public static void getStudentInfo(HashMap<String,String> roomMap)
    52     {
    53         Iterator<String> it = roomMap.keySet().iterator();
    54         while(it.hasNext())
    55         {
    56             String id = it.next();
    57             String name = roomMap.get(id);
    58             System.out.println(id+":"+name);
    59         }
    60     }
    61 }

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

     1 import java.util.*;
     2 class MapTest1 
     3 {
     4     public static void main(String[] args) 
     5         {
     6         System.out.println(getWeek(1));
     7     }
     8     public static String getWeek(int num){
     9         if(num<1 || num>7)
    10             throw new RuntimeException("没有这个星期,请重新输入");
    11         String[] weeks={"","星期一","星期二","星期三","星期四","星期五","星期六","星期日"};
    12         String s=weeks[num];
    13         TreeMap<String,String> tm=new TreeMap<String,String>();
    14         tm.put("星期一","Mon");
    15         tm.put("星期二","Tue");
    16         tm.put("星期三","Wes");
    17         tm.put("星期四","Sta");
    18         tm.put("星期五","Wek");
    19         tm.put("星期六","Sun");
    20         tm.put("星期日","Sun");        
    21         return tm.get(s);
    22     }
    23 }

     总结:

    使用集合的技巧: 

    (1)、看到Array就是数组结构,有角标,查询速度很快。

    (2)、看到Link就是链表结构:增删速度快,而且有特有方法。addFirst; addLast; removeFirst(); removeLast(); getFirst();getLast();

    (3)、看到Hash就是哈希表,就要想要哈希值,就要想到唯一性,就要想到存入到该结构的中的元素必须覆盖hashCode,equals方法。

    (4)、看到Tree就是二叉树,就要想到排序,就想要用到比较。

    比较的两种方式:

    一个是Comparable:覆盖compareTo方法;

    一个是Comparator:覆盖compare方法。

    LinkedHashSet,LinkedHashMap:这两个集合可以保证哈希表有存入顺序和取出顺序一致,保证哈希表有序。

    集合什么时候用?

    当存储的是一个元素时,就用Collection。当存储对象之间存在着映射关系时,就使用Map集合。 保证唯一,就用Set。不保证唯一,就用List。

    九、Collections工具类

    Collections:集合框架的工具类。里面定义的都是静态方法。

    1、Collection和Collections有什么区别?

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

    Collections是集合框架中的一个工具类。该类中的方法都是静态的,提供的方法中有可以对List集合进行排序、二分查找等方法。

    2、Collections中的常用静态方法

    (1)、对List集合进行排序

    1 Collections.sort(List<T> list);//List集合进行元素的自然顺序排序
    2 Collections.sort(List<T> list,Comparator<?super T> c);//按指定的比较器方法排序

     (2)、对List集合进行二分查找

    1 int  Collections.binarySearch(List list, T key);//对List集合进行二分查找,返回角标。
    2 int  Collections.binarySearch(List list,T key,Comparator<T> c);//传入自定义的比较器进行查找

     (3)、对List集合中的对象进行置换

    1 Collections.swap(List list,int i,int j);// 在指定集合的指定位置处交换元素

     (4)、fill方法可以将list集合中所有元素替换成指定元素。

    1 Collections.fill(List<T> list, T obj);//使用指定元素替换指定集合中的所有元素。

     (5)、获取Collection集合中的最大元素

    1 T  Collections.max(Collection coll);//根据元素的自然顺序,返回最大元素
    2 T  Collections.max(Collection coll, Comparator<T> comp);//根据指定比较器产生的顺序,返回最大元素。

     (6)、List集合中新值替换老值

    1 Collections.replaceAll(List list, T oldValue,T newValue);// 使用另一个值替换列表中出现的所有某一指定值。

     (7)、集合进行反转

    1 Collections.reverse(List list);//反转指定集合中元素的顺序
    2 Comparator<T>   reverseOrder();//返回一个比较器,它强行逆转实现了 Comparable 接口的对象。
    3 Comparator<T>   reverseOrder(Comparator<T> comp);// 返回一个比较器,该比较器将强行逆转实现了 Comparable 接口的对象 collection 的自然顺序。

     (8)、使用指定的随机源对指定列表进行置换。

    1 Collections.shuffle(List list);//使用默认随机对集合进行置换。
    2 Collections.shuffle(List list,Random rnd);//使用默认随机对集合进行置换

     (9)、不同步的集合转成同步的集合。

    //原理:定义一个类,将集合所有的方法加同一把锁后返回。
    Collection  Collections.synchronizedCollection(Collection coll);
    List  Collections.synchronizedList(List list);
    Set  Collections.synchronizedSet(Set set);
    Map  Collections.synchronizedMap(Map);

     代码演示:

    (1)、

      1 import java.util.*;
      2 class CollectionsDemo 
      3 {    
      4     public static void main(String[] args) 
      5     {
      6          List<String> list = new ArrayList<String>();
      7             list.add( "abcde");
      8             list.add( "cbad");
      9             list.add( "bb");
     10             list.add( "zzz");
     11             list.add( "cba");
     12             list.add( "a");
     13             sort(list);
     14             binarySearch(list);
     15             swap(list);
     16             fill(list);
     17             max(list);
     18             replaceAll(list);
     19             reverse(list);
     20             shuffle(list);
     21     }
     22     //对List集合进行默认排序,因为TreeSet和TreeMap都能排序了
     23     public static void sort(List<String> list){
     24         //List集合默认排序
     25         Collections.sort(list);
     26         sop(list);//运行结果:[a, abcde, bb, cba, cbad, zzz]
     27         
     28         //指定比较器,按照比较器的比较方式进行比较
     29         Collections.sort(list,new StringLenComp());
     30         sop(list);//运行结果:[a, bb, cba, zzz, cbad, abcde]
     31     }
     32 
     33     //二分查找
     34     public static void binarySearch(List<String> list){
     35         //二分查找在查找之前必须根据元素的自然顺序对集合进行升序排序。
     36         //如果没有对列表进行排序,则结果是不确定的。
     37        //如果列表包含多个等于指定对象的元素,则无法保证找到的是哪一个。 
     38        Collections.sort(list);
     39        sop(list);//[a, abcde, bb, cba, cbad, zzz]
     40        int index=Collections.binarySearch(list,"bb");
     41        sop("index="+index);//index=2
     42 
     43        //指定比较器进行二分查找
     44        int num=Collections.binarySearch(list,"bb",new StringLenComp());
     45        sop(list);//运行结果:[abcde, cbad, bb, zzz, cba, a]
     46        sop("index="+num);//运行结果:index=2
     47 
     48     }
     49 
     50     //对List集合中的对象进行置换
     51     public static void swap(List<String> list){
     52         sop(list);//运行结果:[abcde, cbad, bb, zzz, cba, a]
     53         Collections.swap(list,4,2);
     54         sop(list);//运行结果:[abcde, cbad, cba, zzz, bb, a]
     55     }
     56 
     57     //fill方法可以将list集合中所有元素替换成指定元素。
     58     public static void fill(List<String> list){
     59         sop(list);//运行结果:[abcde, cbad, bb, zzz, cba, a]
     60         Collections.fill(list,"我爱黑马");
     61         sop(list);//运行结果:[我爱黑马, 我爱黑马, 我爱黑马, 我爱黑马, 我爱黑马, 我爱黑马]
     62     }
     63 
     64     //获取Collection集合中的最大元素
     65     public static void max(List<String> list){
     66         String str=Collections.max(list);
     67         sop(str);//运行结果:zzz
     68 
     69         String s=Collections.max(list,new StringLenComp());
     70         sop(s);//运行结果:abcde
     71     }
     72 
     73     //List集合中新值替换老值
     74     public static void replaceAll(List<String> list){
     75         sop(list);//运行结果:[abcde, cbad, bb, zzz, cba, a]
     76         Collections.replaceAll(list,"cba","我要去黑马");
     77         sop(list);//运行结果:[abcde, cbad, bb, zzz, 我要去黑马, a]
     78     }
     79 
     80     //对集合进行反转
     81     public static void reverse(List<String> list){
     82         sop(list);//运行结果:[abcde, cbad, bb, zzz, cba, a]
     83         Collections.reverse(list);
     84         sop(list);//运行结果:[a, cba, zzz, bb, cbad, abcde]
     85         
     86 
     87     }
     88 
     89     //使用指定的随机源对指定列表进行置换。
     90     public static void  shuffle(List<String> list){
     91         sop(list);
     92         Collections.shuffle(list);
     93         sop(list);
     94     }
     95     public static void sop(Object obj){
     96         System.out.println(obj);
     97     }
     98 }
     99 class StringLenComp implements Comparator<String>
    100 {
    101     public int compare(String s1,String s2){
    102         int num=s1.length()-s2.length();
    103         if(num==0)
    104             return s1.compareTo(s2);
    105         return num;
    106     }
    107 }

     (2)、

     1 import java.util.*;
     2 class ReverseOrderDemo
     3 {
     4     public static void main(String[] args) 
     5     {
     6         //返回一个比较器,它强行逆转实现了 Comparable 接口的对象。
     7         TreeSet<String> ts=new TreeSet<String>(Collections.reverseOrder());
     8         ts.add( "abcde");
     9         ts.add( "cbad");
    10         ts.add( "bb");
    11         ts.add( "zzz");
    12         ts.add( "cba");
    13         ts.add( "a");        
    14         System.out.println(ts);//运行结果:[zzz, cbad, cba, bb, abcde, a]
    15 
    16         //对集合进行了两次的反转就又变成了自然排序的顺序了
    17         ts=new TreeSet<String>(Collections.reverseOrder(Collections.reverseOrder()));
    18         ts.add( "abcde");
    19         ts.add( "cbad");
    20         ts.add( "bb");
    21         ts.add( "zzz");
    22         ts.add( "cba");
    23         ts.add( "a");
    24         System.out.println(ts);//运行结果:[a, abcde, bb, cba, cbad, zzz]
    25     }
    26 }

    十、Arrays工具类

    此类包含用来操作数组(比如排序和搜索)的各种方法。里面都是静态的方法。

    (1)、数组按照升序进行排序

    1 Arrays.sort(基本数据类型[]或者 对象[]);
    2 eg:Arrays.sort(int[] arr);// 对指定的 int 型数组按数字升序进行排序。

     (2)、数组进行二分查找

    1 int  Arrays.binarySearch(基本数据类型[] 或者 对象[],key);
    2 eg: Arrays.binarySearch(int[] arr,int key);

     (3)、将数组转换成集合

    1 List  asList(T...a);//T...a可变长度的数组
    2 eg:
    String[] arr = {"abc","kk","qq"};
    3 List<String> list = Arrays.asList(arr);//将arr数组转成list集合。
    
    

     将数组转换成集合,有什么好处呢?用aslist方法,将数组变成集合。

    可以通过List集合中的方法来操作数组中的元素:isEmpty()、contains、indexOf、set;

    注意(局限性)数组是固定长度,不可以使用集合对象增加或者删除等,会改变数组长度的功能方法。比如add、remove、clear。(会报不支持操作异常UnsupportedOperationException);

    如果数组中的元素都是对象。那么变成集合时,数组中的元素就直接转成集合中的元素。

    如果数组中的元素都是基本数据类型,那么会将该数组作为集合中的元素存在。

     1 import java.util.*;
     2 class ArraysDemo
     3 {
     4      public static void main(String[] args){
     5           int[] arr1 = {31,11,51,61};
     6           List< int[]> list1 = Arrays.asList(arr1);
     7            System.out.println(list1);//运行结果:[[I@659e0bfd]
     8            Integer[] arr2 = {31,11,51,61};
     9            List list2 = Arrays.asList(arr2);
    10            System.out.println(list2);//运行结果:[31, 11, 51, 61]
    11       }
    12 }

      (4)、将数组内容变成字符串打印出去

    1 String   Arrays.toString(基本数据类型[] 或者 对象[]);

     代码演示:

     1 import java.util.*;
     2 class ArraysDemo
     3 {
     4     public static void main(String[] args){
     5         int[] arr={34,54,2,5,7,8};
     6         char[] ch={'a','g','j','h','l'};
     7         double[] dou={7.45,0.15,45.12,45,1256,4};
     8         byte[] by={0,1,5,3,5,0};
     9         String[] str={"nihao","hah","heihei"};
    10         System.out.println(Arrays.toString(arr));//运行结果:[34, 54, 2, 5, 7, 8]
    11         System.out.println(Arrays.toString(ch));//运行结果:[a, g, j, h, l]
    12         System.out.println(Arrays.toString(dou));//运行结果:[7.45, 0.15, 45.12, 45.0, 1256.0, 4.0]
    13         System.out.println(Arrays.toString(by));//运行结果:[0, 1, 5, 3, 5, 0]
    14         System.out.println(Arrays.toString(str));//运行结果:[nihao, hah, heihei]
    15     }
    16 }

     十一、将集合转成数组

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

    1 Object[]  toArray();
    2 T[]  toArray(T[] a);//返回数组的运行时类型与指定数组的运行时类型相同

     集合转成数组,可以对集合中的元素操作的方法进行限定,不允许对其进行增删。只要获取这些元素即可。 toArray方法需要传入一个指定类型的数组,那么长度该如何定义呢?

    当指定类型的数组长度小于了集合的size,那么该方法内部会创建一个新的数组。长度为集合的size。

    当指定类型的数组长度大于了集合的size,就不会新创建了数组,而是使用传递进来的数组。

    所以建议,在传递指定类型数组时,最好的方式就是指定的长度和size相等的数组。

     1 import java.util.*;
     2 class ArraysDemo
     3 {
     4     public static void main(String[] args){
     5         List<Integer> list=new ArrayList<Integer>();
     6         list.add(5);
     7         list.add(4);
     8         list.add(10);
     9         list.add(12);
    10         list.add(54);
    11         Integer[] arr=list.toArray(new Integer[list.size()]);//刚刚好的数组长度
    12         for (int x=0;x<arr.length ;x++ )
    13         {
    14             System.out.println(arr[x]);
    15         }
    16     }
    17 }

     未完待续.............

     注:菜鸟日记,如有错误欢迎大神指正,欢迎探讨!!

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

  • 相关阅读:
    小素典会员订阅协议
    vue项目自动构建工具1.0,支持多页面构建
    spring boot 框架根據 sql 創建語句自動生成 MVC層類代碼
    使用 docsify 創建自己的 markdown 文檔系統
    “衣”及其部分屬字
    js原型鏈與js繼承解析
    js 中怎么获取session 值和HTML标签的属性值
    layui table动态表头 改变表格头部 重新加载表格的方法
    throw throws Throwable 关联于区别
    静态代理和动态代理的区别和联系
  • 原文地址:https://www.cnblogs.com/521Android/p/4722075.html
Copyright © 2011-2022 走看看