Java集合--简单讲解

来源:互联网 发布:淘宝试用报告草稿在哪 编辑:程序博客网 时间:2024/05/22 06:11

  • 数组与集合
  • 集合整体结构图
  • Collection和Iterator
    • List接口
      • List示例-String类型
      • 遍历集合的方法
        • Iterator迭代器
        • forEach循环
      • 泛型的初步
        • 为什么使用泛型
        • 使用泛型解决示例
      • List示例-Student类型
      • List排序
        • List自定义排序
        • Comparator示例
        • Camparable和Comparator
      • 面试题
    • Set接口
      • 哈希表
      • HashSet
        • HashSet 怎样存储对象
      • TreeSet
    • Map接口
      • HashMap
      • Map的遍历
      • TreeMap
      • HashMap与Hashtable
    • Collections工具类

数组与集合

  • 在创建Java数组时,数组的长度必需要指定,数组一旦创建好之后,长度不改变,在同一个数组中只能存放同一种类型的数据(基本类型和引用类型)
  • 为了使程序能方便的存储和操作数目不固定的一组数据,JDK类库中提供了Java集合,所有的Java集合都在java.util包中,在集合中,只能存放对象的引用,而不能存放基本数据类型
  • Java集合主要有3种重要的类型:
    • List:是一个有序集合,可以存放重复的数据;
    • Set:是一个无序集合,不允许存放重复的数据;
    • Map:是一个无序集合,集合中包含一个键对象,一个值对象,键对象不允许重复,值对象可以重复(身份证号码–姓名)
      这里写图片描述

集合整体结构图

这里写图片描述

Collection和Iterator

  • Collection是List和Set的父接口,在Collection中定义了一些主要方法

这里写图片描述

List接口

  • List接口是一个有序集合,可以放入重复数据;
  • 下面主要有两个实现:ArrayList和LinkedList,他们都是有顺序的,也就是放进去是什么顺序,取出来还是什么顺序,也就是基于线性存储,可以看作是一个可变的数组
    • ArrayList:查询数据比较快,添加和删除数据比较慢(基于可变数组)
    • LinkedList:查询数据比较慢,添加和删除数据比较快(基于链表数据结构)
    • Vector:Vector已经不建议使用,Vector中的方法都是同步的,效率慢,已经被ArrayList取代
      这里写图片描述

List示例-String类型

public class Test01 {    public static void main(String[] args) {        String s1= new String("zhangsan");        String s2= new String("lisi");        String s3= new String("wangwu");        List l = new ArrayList();        l.add(s1);        l.add(s2);        l.add(s3);        l.remove(1);//      System.out.println(l.size());//      System.out.println(l.contains(s2));//      System.out.println(l.get(0));//      System.out.println(l.get(1));//      for (int i = 0; i < l.size(); i++) {//          System.out.println(l.get(i));//      }        Iterator it = l.iterator(); //迭代器        while(it.hasNext()){            String s =(String) it.next();            System.out.println(s);                  }    }}

遍历集合的方法

Iterator迭代器

     Iterator<E> i =  list.iterator();     public boolean hasNext();     public E next();

这里写图片描述

forEach循环

这里写图片描述

泛型的初步

泛型能更早的发现错误,如类型转换错误,通常在运行期才会发现,如果使用泛型,那么在编译器将会发现,通常错误发现的越早,越容易调试,越容易减少成本

为什么使用泛型

    import java.util.*;    public class GenericTest01 {        public static void main(String[] args) {            List l = new ArrayList();            l.add(1);            l.add(2);            l.add(3);            for (Iterator iter=l.iterator(); iter.hasNext();) {                 //出现了java.lang.ClassCastException异常            //这种转型错误在运行期被发现了            //错误发现的越早越好,最好在编译器能发现类似的错误            //如果想在编译器发现类似的错误,必须使用泛型            String s = (String)iter.next();            System.out.println(s);        }    }   }

使用泛型解决示例

    import java.util.*;    public class GenericTest02 {        public static void main(String[] args) {            List<Integer> l = new ArrayList<Integer>();            l.add(1);            l.add(2);            l.add(3);               //不能将abc放到集合中,因为使用泛型,在编译器就可以返现错误            //l.add("abc");            for (Iterator<Integer> iter=l.iterator(); iter.hasNext();) {                        //因为使用泛型,在编译器就可以发现错误            //String s = (String)iter.next();            //使用泛型可以不用进行强制转换            //Integer s = (Integer)iter.next();            //可以直接取得相应的元素,使用泛型返回的是真正的类型            Integer s = iter.next();            System.out.println(s);        }    }   }

List示例-Student类型

    class Student {        String no;        String name;        int age;        public Student(String no,String name, int age) {            this.no = no;            this.name = name;            this.age = age;        }        @Override        public boolean equals(Object obj) {            if (this == obj)                return true;            if (obj == null)                return false;            if (getClass() != obj.getClass())                return false;                Student other = (Student) obj;            if (age != other.age)                return false;            if (name == null) {            if (other.name != null)                return false;            } else if (!name.equals(other.name))                return false;            if (no == null) {            if (other.no != null)                return false;            } else if (!no.equals(other.no))                return false;                return true;        }    }    public class Test {        public static void main(String[] args) {            Student s1 = new Student("001","zs", 15);            Student s2 = new Student("002","ls", 15);            Student s3 = new Student("003","ww", 15);            Student s4 = new Student("003","ww", 15);            List l = new ArrayList();            l.add(s1);            l.add(s2);            l.add(s3);        //针对对象类型,如果要使用contains方法,必须要重写equals        //  if(!l.contains(s4)){        //      l.add(s4);                  //  }        //          //  System.out.println(l.size());        //  for (Object o : l) {        //      Student s = (Student)o;        //      System.out.println(s.name);        //  }        //          //  System.out.println(l.contains(s4));            Iterator it = l.iterator();            while(it.hasNext()){                Student s = (Student)it.next();                System.out.println(s.name+":"+s.age);                       }        }    }

List排序

  • void Collections.sort(List);

        String person1 = "zhang3";    String person2 = "li4";    String person3 = "wang5";    List<String> list = new ArrayList<>();    list.add(person1);    list.add(person2);    list.add(person3);    Collections.sort(list);    Iterator<String> it = list.iterator();    while(it.hasNext()) {        System.out.println(it.next());}

    Student stu1=new Student("zhang2",20);    Student stu2=new Student("zhang1",10);    Student stu3=new Student("zhang1",30);    List<Student> list1=new ArrayList<Student>();    list1.add(stu1);    list1.add(stu2);    list1.add(stu3);    //由于没有实现Comparable接口,无法通过编译    Collections.sort(list);     Iterator<Student> it=list.iterator();    while(it.hasNext()){        Student student=it.next();        System.out.println(student.getName());    }

这里写图片描述

  • String+8种包装类默认已经实现了Comparable接口
  • 先按年龄排序,再按序号

     Student s = (Student)o; int i = this.age - s.age; if(i==0){     return this.no.compareTo(s.no); } return i;

List自定义排序

  • Collection类的sort方法有个重载方法:sort(Listlist,Comparator

Comparator示例

  • 可以通过实现Comparator自定义排序规则
    这里写图片描述

这里写图片描述

Camparable和Comparator

  • 一个类实现了Camparable接口则表明这个类的对象之间是可以相互比较的,这个类对象组成的集合就可以直接使用sort方法排序,如果集合中使用比较功能,必须保证集合中的数据类型是一致的。
  • Comparator可以看成一种算法的实现,将算法和数据分离,Comparator也可以在下面两种环境下使用:
    • 1.类没有考虑到比较问题而没有实现Comparable,可以通过Comparator来实现排序而不必改变对象本身
    • 2.可以使用多种排序标准,比如升序、降序等

面试题

这里写图片描述

Set接口

  • Set:是一个无序集合,不允许放重复的数据,主要有两个实现类–HashSet和TreeSet
    这里写图片描述

哈希表

  • 哈希表是一种数据结构,哈希表能够提供快速存取操作。哈希表是基于数组的,所以也存在缺点,数组一旦创建将不能扩展
  • 正常的数组,如果需要查询某个值,需要对数组进行遍历,只是一种线性查找,查找的速度比较慢,如果数组中的元素值和下标能够存在明确的对应关系,那么通过数组元素的值就可以换算出数组元素的下标,通过下标就可以快速定位数组元素,这样的数组就是哈希表。一张哈希表:
    这里写图片描述

HashSet

  • HashSet中的数据是无序的不可重复的。HashSet按照哈希算法存取数据的,具有非常好的性能,它的工作原理是这样的:当向HashSet中插入数据的时候,他会调用对象的hashCode得到该对象的哈希码,然后根据哈希码计算出该对象插入到集合中的位置
    String person1=”zhang3”;
    String person2=”li4”;
    String person3=”wang5”;

    Set<String> set1=new HashSet<String>();set1.add(person1);set1.add(person2);set1.add(person3);Iterator<String> it=set1.iterator();while(it.hasNext()){    System.out.println(it.next());//输出是没有顺序的}
  • HashSet 元素不可重复

    String person1="zhang3";String person2="li4";String person3="wang5";String person3="wang5";Set<String> set1=new HashSet<String>();set1.add(person1);set1.add(person2);set1.add(person3);set1.add(person4);Iterator<String> it=set1.iterator();while(it.hasNext()){    System.out.println(it.next());}zhang3wang5li4
  • HashSet 没有成功的去除重复元素

     Student stu1=new Student(“zhang2",20);Student stu2=new Student("zhang1",10);Student stu3=new Student("zhang3",30);Student stu4=new Student("zhang3",30);Set<Student> set2=new HashSet<Student>();set2.add(stu1);set2.add(stu2);set2.add(stu3);set2.add(stu4);Iterator<Student> it=set2.iterator();while(it.hasNext()){    Student student=it.next();    System.out.println(student.getName());;}
  • 是重写了Student的equals方法

    public class Student1 implements Comparable<Student>{    String name;    int age;    @Override    public boolean equals(Object obj){        System.out.println("equals方法被调用");        if(this==obj)               return true;        if(obj==null)               return false;        if(getClass()!=obj.getClass())              return false;        Student1 other=(Student1)obj;        if(age!=other.age)              return false;        if(name==null){            if(other.name!=null)                 return false;        }else if(!name.equals(other.name)){            return false;        }        return true;    }}
  • HashSet 仍然没有成功的去除重复元素,且equals没有调用

    Student stu1=new Student("sun2",20);Student stu2=new Student("sun1",10);Student stu3=new Student("sun3",30);Student stu4=new Student("sun3",30);Set<Student> set2=new HashSet<Student>();set2.add(stu1);set2.add(stu2);set2.add(stu3);set2.add(stu4);Iterator<Student> it=set2.iterator();while(it.hasNext()){    Student student=it.next();    System.out.println(student.getName());;}
  • 采取HashSet存储对象类型数据,除了重写equals(),还必须要重写了hashCode方法后

    @Overridepublic int hashCode() {    System.out.println("hashCode方法被调用了");    final int prime = 31;    int result = 1;    result = prime * result + age;    result = prime * result + ((name == null) ? 0 : name.hashCode());    return result;}

HashSet 怎样存储对象

  • Object中定义了 publicinthashCode()
  • HashSet怎样存储对象
    • 调用hashCode()
    • 当发现两个对象hashCode值相同时,再调用equals
  • HashCode方法的覆盖建议
    • 内容相同的对象,hashCode值一样
    • 最佳实践:不要自己提供hashCode值得算法,二是使用IDE自动生成,这是hashCode数学专家提供的算法,更可靠
    • hashCode和equals方法最好成对重写,不要只重写一个

TreeSet

  • SortedSet接口的实现类
  • 可以排序
  • 必须:元素实现Comparable接口;或调用TreeSet(Comparator

Map接口

  • 常用方法
    • key不可以重复、value可以重复
    • put(K key,Vvalue);
    • get(Object key);
    • remove(Object key);
    • clear();
    • isEmpty();
    • size();
      这里写图片描述

HashMap

  • HashMap的常规使用

    Map<String,String> map=new HashMap<>();map.put("key1","value1");map.put("key2","value2");map.put("key3","value2");map.put("key1","value4");//替换了第一次放入的value1System.out.println(map.get(“key1”));//value4System.out.println(map.get("key2")); //value2System.out.println(map.get("key3")); //value2System.out.println(map.get(“key8”));//null
  • HashMap的key也是通过Hash算法 过滤重复
  • Map的key一般都应用String
    • 如果想用自己写的类作为key值,那么就必须重写hashCode()方法和equals()方法,而且要保证对象不可变,也就是和String一样,一旦创建了这个对象,就不可修改。

Map的遍历

  • 值遍历

    Map<String,String> map=new HashMap<>();map.put("key1","value1");map.put("key2","value2");map.put("key3","value2");map.put("key1","value4");//替换了第一次放入的value1Collection<String> collection=map.values();for(String str:collection){    System.out.println(str);}/** value2* value2* value4*/
  • 键遍历

        Map<String,String> map=new HashMap<String,String>();map.put("key1","value1");map.put("key2","value2");map.put("key3","value2");map.put("key1","value4");//替换了第一次放入的value1Set<String> set=map.keySet();for(String str:set){    System.out.println(str);}   /*    * key3    * key2    * key1    */
  • 键值遍历一

    Map<String,String> map=new HashMap<String,String>();map.put("key1","value1");map.put("key2","value2");map.put("key3","value2");map.put("key1","value4");//替换了第一次放入的value1Set<String> set=map.keySet();for(String key:set){    System.out.println(key+":"+map.get(key));}   /*    * key3:value2    * key2:value2    * key1:value4    */
  • 键值遍历二

    • Entry是Map接口的一个内部接口,即子接口。 先有Map集合再有映射关系,是Map集合的内部事务 Map.Entry中存的是映射关系这种数据类型。

          Map<String,String> map=new HashMap<String,String>();    map.put("key1","value1");    map.put("key2","value2");    map.put("key3","value2");    map.put("key1","value4");//替换了第一次放入的value1    Set<String> set=map.keySet();    for(Entry<String,String> entry:map.entrySet()){    System.out.println(entry.getKey()+":"+entry.getValue());    }   /*    * key3:value2    * key2:value2    * key1:value4    */

TreeMap

  • TreeMap 可以对key应用排序

     Map<String,String> map1=new TreeMap<String,String>();map1.put("b", "value1");map1.put("d", "value2");map1.put("c", "value2");map1.put("a", "value4");for(Entry<String,String> entry:map.entrySet()){System.out.println(entry.getKey()+":"+entry.getValue());}    /*    * a:value4    * b:value1    * c:value2    * d:value2    */
  • TreeMap的key是通过Comparable接口 过滤重复 排序,也可以通过Comparator接口的实现类的对象来过滤重复排序

  • Map的key一般都应用String多

HashMap与Hashtable

  • Hashtable 与 HashMap的区别
    这里写图片描述

Collections工具类

  • Collections位于java.util包中,提供了一系列实用的方法,如:对集合排序,对集合中的内容查找等

    import java.util.*;public class CollectionsTest01 {    public static void main(String[] args) {        List l = new ArrayList();        l.add(5);        l.add(1);        l.add(4);        l.add(2);        for (Iterator iter=l.iterator(); iter.hasNext();) {            System.out.println(iter.next());        }        System.out.println(“—List排序---");        Collections.sort(l);        for (Iterator iter=l.iterator(); iter.hasNext();) {            System.out.println(iter.next());        }        System.out.println("-----");                Set set = new HashSet();        set.add(10);        set.add(1);        set.add(4);        set.add(9);        //不能直接对set排序        //Collections.sort(set);        List setList = new ArrayList(set);        Collections.sort(setList);        for (Iterator iter=setList.iterator(); iter.hasNext();) {            System.out.println(iter.next());        }        System.out.println(“---二分法查找--");        int index = Collections.binarySearch(setList, 9);        System.out.println("index=" + index);        System.out.println(“---反转集合元素--");        Collections.reverse(setList);        for (Iterator iter=setList.iterator(); iter.hasNext();) {            System.out.println(iter.next());        }    }   }
原创粉丝点击