• Java(十四)——集合


    集合

    一、集合分类及关系

    Java的java.util包主要提供了以下三种类型的集合:

    • List:一种有序元素可重复列表的集合,例如,按索引排列的StudentList
    • Set:一种无序元素不能重复的集合,例如,所有无重复名称的StudentSet
    • Map:一种通过键值(key-value)查找的映射表集合,例如,根据Studentname查找对应StudentMap

    Java标准库自带的java.util包提供了集合类:Collection,它是除Map外所有其他集合类的根接口

    二、集合的特点

    • 一是实现了接口和实现类相分离,例如,有序表的接口是List,具体的实现类有ArrayListLinkedList

    • 二是支持泛型,我们可以限制在一个集合中只能放入同一种数据类型的元素

      ArrayList<String> al = new ArrayList<String>();
      
    • 三是访问集合总是通过统一的方式——迭代器(Iterator)来实现

    三、List接口

    1、接口方法

    List接口有两个实现类:ArrayList类LinkedList类

    // List接口的接口方法
    void add(E e)			// 在末尾添加一个元素
    void add(int index, E e)       // 在指定索引添加一个元素
    int remove(int index)			// 删除指定索引的元素
    int remove(Object e)		// 删除某个元素
    E get(int index)			// 获取指定索引的元素
    int size()			// 获取链表大小(包含元素的个数)
    

    2、实现类区别

    • ArrayList类
      添加元素,但是数组已满,没有空闲位置的时候,ArrayList先创建一个更大的新数组,然后把旧数组的所有元素复制到新数组,紧接着用新数组取代旧数组

    • LinkedList类

      它的内部每个元素都指向下一个元素

    ArrayList LinkedList
    获取指定元素 速度很快 需要从头开始查找元素
    添加元素到末尾 速度很快 速度很快
    在指定位置添加/删除 需要移动元素 不需要移动元素
    内存占用 较大

    所以,优先使用ArrayList

    3、遍历List

    • 使用list.size()进行for循环,只能应用于ArrayList,不能应用于LinkedList

    • 使用迭代器Iterator来访问ListIterator是由List的实例调用iterator()方法的时候创建的

    Iterator对象有两个方法:boolean hasNext()判断是否有下一个元素,E next()返回下一个元素

    import java.util.Iterator;
    import java.util.List;
    
    public class Main {
        public static void main(String[] args) {
            List<String> list = List.of("apple", "pear", "banana");
            for (Iterator<String> it = list.iterator(); it.hasNext(); ) {
                String s = it.next();
                System.out.println(s);
            }
        }
    }
    
    

    for each循环遍历集合

    // for each循环本身就可以帮我们使用Iterator遍历
    
    import java.util.List;
    
    public class Main {
        public static void main(String[] args) {
            List<String> list = List.of("apple", "pear", "banana");
            for (String s : list) {
                System.out.println(s);
            }
        }
    }
    
    

    4、比较List中的元素是否相等

    • List中查找元素时,List的实现类通过元素的equals()方法比较两个元素是否相等,因此,放入的元素必须正确覆写equals()方法,Java标准库提供的StringInteger等已经覆写了equals()方法

    • 如果不调用Listcontains()indexOf()这些方法,那么放入的元素就不需要实现equals()方法。

    元素对象重写equals()方法:

    1. 先确定实例“相等”的逻辑,即哪些字段相等,就认为实例相等;

    2. instanceof判断传入的待比较的Object是不是当前类型,如果是,继续比较,否则,返回false

    3. 对引用类型用Objects.equals(a, b)比较,对基本类型直接用==比较。

    public boolean equals(Object o) {
        if (o instanceof Person) {
            Person p = (Person) o;
            boolean nameEquals = false;
            if (this.name == null && p.name == null) {
                nameEquals = true;
            }
            if (this.name != null) {
                nameEquals = this.name.equals(p.name);
            }
            return nameEquals && this.age == p.age;
        }
        return false;
    }
    
    // 重写equals()方法,简写版
    public boolean equals(Object o) {
        if (o instanceof Person) {
            Person p = (Person) o;
            return Objects.equals(this.name, p.name) && this.age == p.age;
        }
        return false;
    }
    

    四、Set接口

    放入Set的元素,要正确实现equals()hashCode()方法,否则该元素无法正确地放入Set

    1、接口方法

    boolean add(E e)		// 将元素添加进Set<E>
    boolean remove(Object e)		// 将元素从Set<E>删除
    boolean contains(Object e)   //	判断是否包含元素
    

    2、实现类

    • HashSet是无序的,因为它实现了Set接口,并没有实现SortedSet接口
    • TreeSet是有序的,因为它实现了SortedSet接口

    3、遍历

    public class Main {
        public static void main(String[] args) {
            Set<String> set = new HashSet<>();
            set.add("apple");
            set.add("banana");
            set.add("pear");
            set.add("orange");
            for (String s : set) {
                System.out.println(s);
            }
        }
    }
    

    五、Map接口

    Map也是一个接口,最常用的实现类是HashMap

    Map是一种 键-值 映射表,当我们调用put(K key, V value)方法时,就把keyvalue做了映射并放入Map。当我们调用V get(K key)时,就可以通过key获取到对应的value。如果key不存在,则返回null

    1、存键值对——put(key, value)

    public class Main {
        public static void main(String[] args) {
            Student s = new Student("Xiao Ming", 99);
            Map<String, Student> map = new HashMap<>();
            map.put("Xiao Ming", s); // 将"Xiao Ming"和Student实例映射并关联
    
        }
    }
    

    2、取数据——get(key)

    public class Main {
        public static void main(String[] args) {
            Student s = new Student("Xiao Ming", 99);
            Map<String, Student> map = new HashMap<>();
            map.put("Xiao Ming", s); // 将"Xiao Ming"和Student实例映射并关联
    		Student target = map.get("Xiao Ming"); // 通过key查找并返回映射的Student实例
    
        }
    }
    
    

    3、其他方法

    boolean containsKey(K key)    // 查询某个key是否存在
    boolean	isEmpty()  // 判断是否为空
    Set<K>	keySet()    //  获取map中所有key,一个Set集合
    V	remove(Object key)   //  更具key删除数据
    int	size()    // 获取 key-value的数量
    

    4、遍历Map

    (1)遍历 key来获取所有value

    通过for each遍历keySet()

    // 遍历 key来获取所有value
    public static void main(String[] args) {
            Map<String, Integer> map = new HashMap<>();
            map.put("apple", 123);
            map.put("pear", 456);
            map.put("banana", 789);
            for (String key : map.keySet()) {
                Integer value = map.get(key);
                System.out.println(key + " = " + value);
            }
        }
    

    (2)同时遍历key和value

    for each遍历entrySet(),直接获取key-value

    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<>();
        map.put("apple", 123);
        map.put("pear", 456);
        map.put("banana", 789);
        // 利用entrySet()将映射关系存到Set中
        for (Map.Entry<String, Integer> entry : map.entrySet()) {
            // 通过Entry对象的getKey,getValue获取 key和value
            String key = entry.getKey();
            Integer value = entry.getValue();
            System.out.println(key + " = " + value);
        }
    }
    

    5、获取value原理

    • 它内部通过空间换时间的方法,用一个大数组存储所有value,并根据key直接计算出value应该存储在哪个索引

    • 计算索引是调用key对象的hashCode()方法

    6、注意点

    key 是自定义类型的时候,必须重写hashCode()equals()

  • 相关阅读:
    MySQL_01 常用命令
    32_Go基础(TCP通信)
    oracle查询优化
    Eclipse中自动添加注释(作者,时间)
    java注解的学习
    JqueryeasyUIdatagrid参数之 queryParams
    Eclipse中,打开文件所在文件夹的插件,及设置
    更改Zend Studio/Eclipse代码风格主题
    JAVA中使用File类批量重命名文件及java.io.File的常见用法
    java面试笔试题大全
  • 原文地址:https://www.cnblogs.com/linagcheng/p/12186389.html
Copyright © 2020-2023  润新知