Java集合--简单讲解

数组与集合

  • 在创建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());
    }
    
    zhang3
    wang5
    li4
    
  • 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方法后

    @Override
    public 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");//替换了第一次放入的value1
    System.out.println(map.get(“key1”));//value4
    System.out.println(map.get("key2")); //value2
    System.out.println(map.get("key3")); //value2
    System.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");//替换了第一次放入的value1
    Collection<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");//替换了第一次放入的value1
    Set<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");//替换了第一次放入的value1
    Set<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());
            }
        }   
    }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

苦修的木鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值