java集合框架:List/Set 接口和其子类

1. List接口

  • java.util.List接口 extends Collecton接口

  • 特点:

    • 有序的集合
    • 索引,包含了一些带索引的方法
    • 允许存储重复的元素
  • 带索引的方法(特有)(注意防止索引越界异常)

    • public void add(int index ,E element):将元素添加到指定位置。
    • public E get(int index):返回集合中指定位置的元素
    • public E remove (int index):移除列表中指定的元素,返回的是被移除的元素
    • public E set (int index , E element):用指定元素替换集合中指定位置的元素,返回值为更新前的元素。
public class Demo01 {
    public static void main(String[] args) {
        //使用多态创建一个集合对象
        List<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("d");
        list.add("a");
        System.out.println(list);//[a, b, c, d, a] 重写了toString()方法
        // public void add(int index ,E element):将元素添加到指定位置。
        list.add(3,"new3");
        System.out.println(list);//[a, b, c, new3, d, a]

        //remove()
        System.out.println("被移除的元素:"+list.remove(2));//被移除的元素:c
        System.out.println(list);//[a, b, new3, d, a]

        //set()
        System.out.println("被替换的元素:"+list.set(4,"A"));//被替换的元素:a
        System.out.println(list);//[a, b, new3, d, A]

        //遍历三种方式:
        // 1.普通for循环
        for (int i=0;i<list.size();i++){
            System.out.println(list.get(i));
        }
        // 2.使用迭代器
        Iterator<String> it=list.iterator();
        while (it.hasNext()){
            System.out.println(it.next());
        }
        //增强for
        for (String s:list){
            System.out.println(s);
        }
    }
}


2. List的子类

ArrayList

  • java.util.ArrayList集合数据存储的结构是数组结构
  • 增删慢、查找快
  • 此实现不是同步的

LinkedList集合

  • java.util.LinkedList集合数据存储的结构是链表结构
  • 查询慢、增删快
  • 是一个双向链表:有大量对首位操作的方法
  • 使用特有的方法,不能使用多态
  • 此实现不是同步的

Vector

  • Vector底层也是数组,是同步的,速度慢;
  • 从Java 2平台v1.2,这个类被改造为实现List接口,可以使用List接口里的方法
  • 如果不需要线程安全的实现,建议使用ArrayList代替Vector


3. Set接口

  • 不包含重复元素的集合
  • 没有索引,没有带索引的方法,不能使用普通的for循环遍历

HashSet

  • 此类实现Set接口,由哈希表(实际为HashMap实例)支持。
  • 是个无序集合:对集合的迭代顺序不作任何保证; 特别是,它不能保证该顺序恒久不变。
  • 允许null元素。
  • 此实现不是同步的

哈希值

  • 是一个十进制的整数,由系统随机给出(就是对象的地址,是一个逻辑地址,是模拟出来得到的地址,不是数据实际存储的物理地址)

  • 在Object类有一个方法,可以获取对象的哈希值:int hashCode()

     //hashCode方法的源码:
     public native int hashCode();
     //native:代表该方法调用的是本地操作系统的方法
     
     //toString方法源码:也用了hashCode方法,输出的逻辑地址是一样的
     public String toString(){
         return getClass().getName()+"@"+Integer.toHexString(hashCode());
     }
    
  • String类的哈希值:String类重写了Object类的hashCode方法

    	String s1=new String("abc");
    	String s2=new String("abc");
    	System.out.println(s1.hashCode());//96354
    	System.out.println(s2.hashCode());//96354
    
  • 两个元素不同,但是哈希值相同:哈希冲突

    	System.out.println("重地".hashCode());//1179395
        System.out.println("通话".hashCode());//1179395
    

HashSet集合存储数据的结构:哈希表

  • jdk1.8之前:哈希表=数组+链表

  • jdk1.8之后:哈希表=数组+链表;哈希表=数组+红黑树(提高查询的速度)

  • 哈希表的特点:速度快

  • 数组结构:把元素进行了分组(相同哈希值的元素是一组),链表/红黑树结构把相同哈希值的元素连接到一起

    存储数据到集合中时:先计算元素的哈希值

    如果链表的长度超过了8位,那么就会把链表转换为红黑树


HashSet存储自定义类型元素

  • Set集合不允许重复元素的原理

    • Set集合在调用add方法时,回调用元素的hashCode方法和equals方法判断元素是否重复
  • HashSet存放自定义类型元素时,需要重写对象中的hashCode()equals()方法,建立自己的比较方式,才能保证HashSet集合中的对象唯一

//例:要求:同名同年龄的人只能存储一次
public class Person {
    private String name;
    private int age;
    //重写equals方法
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age &&
                Objects.equals(name, person.name);
    }
    //重写hashCode方法
    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
//测试类
public class Demo01 {
    public static void main(String[] args) {
      HashSet<Person> set=new HashSet<>();
      Person p1=new Person("aa",20);
      Person p2=new Person("bb",22);
      Person p3=new Person("aa",20);
        System.out.println(p1.hashCode());//97205
        System.out.println(p2.hashCode());//98199
        System.out.println(p3.hashCode());//97205
        System.out.println(p1==p3);//false
        System.out.println(p1.equals(p3));//true
        set.add(p1);
        set.add(p2);
        set.add(p3);
        System.out.println(set);//[Person{name='aa', age=20}, Person{name='bb', age=22}]
    }
}


LinkedHashSet

  • HashSet下有一个子类java.util.LinkedHashSet,是链表和哈希表组合的一个数据存储结构;
  • 此实现与 HashSet 的不同之外在于,后者维护着一个运行于所有条目的双重链接列表,多了一条链表用来记录元素的存储顺序,保证元素有序
posted @ 2020-12-30 18:30  迪迦是真的  阅读(203)  评论(0)    收藏  举报
//复制代码按钮 //代码行号 //评论