zoukankan      html  css  js  c++  java
  • 集合(Java)

    Java集合简介

    数组的限制:

    • 数组初始化后大小不可取
    • 数组只能按索引顺序存取

    Java.util.Collection

    除Map外的所有其他集合类的根接口。java.util包主要提供三种类型的集合:List、Set、Map

    • List 一种有序列表的的集合,按索引排列
    • Set一种没有重复元素的集合
    • Map一种通过键值key-value查找的映射表集合
    • Java集合的设计有几个特点:一是实现了接口和实现类相分离,例如有序表的接口是List,具体的实现类有ArrayList、linkList,二是支持泛型,限制在一个集合中只能放入同一种数据类型的元素
    • Java访问集合通过统一的方式迭代器Iterator来实现。

    使用List

    ArrayList把添加和删除的操作封装起来,本质是数组。对List的操作,相当于对数组的操作。

    List接口,几个主要接口方法:

    • 末尾添加一个元素,void add(E e)
    • 指定索引添加一个元素 void add(int index,E e)
    • 删除指定索引的元素 int remove(int inde)
    • 删除某个元素 int remove(Object e)
    • 获取指定索引的元素 E get(int index)
    • 获取链表大小 int size()

    LinkedList(链表),也实现了List接口。

    Array LinkedList
    获取指定元素 速度很快 需要从头开始查找元素
    添加元素到末尾 速度很快 速度很快
    在指定位置添加/删除 需要移动元素 不需要移动元素
    内存占用 较大
    • List允许添加null
    • 用迭代器Iterator访问List
    • Iterator对象有两个方法:boolean hasNext()是否有下一个元素 E next()返回下一个元素
    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);
            }
        }
    }
    

    List和Array之间的转换

    • toArray(T[])方法的泛型参数并不是List接口定义的泛型参数,所以,我们实际上可以传入其他类型的数组,例如我们传入Number类型的数组,返回的仍然是Number类型
    • 如果我们传入类型不匹配的数组,例如,String[]类型的数组,由于List的元素是Integer,所以无法放入String数组,这个方法会抛出ArrayStoreException。
    • 将Array变为List
    Integer[] array = { 1, 2, 3 };
    List<Integer> list = List.of(array);
    

    编写equals方法

    • List内部并不是通过==判断两个元素是否相等,而是使用equals()
    • 要使用List的contains()必须要覆写equals()方法
    • equals()方法要满足几个特性:自反性,对称性,传递性,一致性
    public boolean equals(Object o) {
        if (o instanceof Person) {
            Person p = (Person) o;
            return this.name.equals(p.name) && this.age == p.age;
        }
        return false;
    }//覆写equals 字符串用equals 数值用==
    

    使用Map

    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实例
            System.out.println(target == s); // true,同一个实例
            System.out.println(target.score); // 99
            Student another = map.get("Bob"); // 通过另一个key查找
            System.out.println(another); // 未找到返回null
        }
    }
    
    class Student {
        public String name;
        public int score;
        public Student(String name, int score) {
            this.name = name;
            this.score = score;
        }
    }
    
    
    • Map<K,V>是一种键值映射表,put放入map,get 获取对应的value,containsKey()判断是否有这个Key
    • Map也是一个接口,常用实现的类时HashMap
    • 重复放入key-value不会有问题,但是一个key只能有一个value,会覆盖。
    • key不能重复,value可以重复

    遍历Map

    • map.keyset() 键的值域
    • Map遍历顺序不一定,随机的

    编写equals和hashCode

    • HashMap内部的数组长度总是2的次方
    • 我们覆写equals()和hashCode()时一定要确定两个对象相等,他们的hashCode要相等
    • 两个对象不相等,hascode尽量不相等
    • 通过key计算索引的方式就是调用key对象的hashCode()方法,返回一个int整数。HashMap通过这个方法直接定位Key对应的value索引,继而返回value

    使用TreeMap

    Map接口有两个实现类,一个是HashMap,另一个是TreeMap。HashMap内部的Key是无序的,而SortMap接口的实现类TreeMap内部Key是有序的。

    • HashMap是一种以空间换时间的映射表,SortMap会对KEY排序,实现类是TreeMAP
    • 使用TreeMap,放入的Key必须实现Comparable接口,定义比较规则

    使用Properties

    编写程序时,需要读写配置文件,一般Key-Value是String-String类型的。Java集合库提供了一个Properties来表示配置。本质是一个Hashtable。

    • 配置文件信息
    • 以.properties为扩展名,以#为开头
    # setting.properties
    
    last_open_file=/data/hello.txt
    auto_save_interval=60
    
    String f = "setting.properties";
    Properties props = new Properties();
    props.load(new java.io.FileInputStream(f));
    
    String filepath = props.getProperty("last_open_file");
    String interval = props.getProperty("auto_save_interval", "120");
    
    • 读取配置文件一共有三步
    • 创建Properties实例
    • 调用load()读取文件
    • 调用getProperty获取配置
    • InputStream和Reader的区别是一个是字节流,一个是字符流。
    • 字符流用CHAR表示,不涉及编码问题,UTF-8

    使用Set

    • 用于存储不重复的元素集合。
    • 添加元素 add()
    • 删除元素 remove()
    • 判断是否包含元素 contains()

    Set的实现类HashSet和TreeSet,而HashSet是对HashMap的一个封装。同样的,HashSet无序,TreeSet有序。

    使用Queue

    • 通过add()/offer()将元素添加到队尾
    • 通过remove/poll取首元素并删除
    • 通过element/peek获取首元素但不删除

    PriorityQueue优先队列

    • 放入优先队列的元素,必须实现Comparable接口,队列会根据排序顺序决定优先级
    public class Main {
        public static void main(String[] args) {
            Queue<User> q = new PriorityQueue<>(new UserComparator());
            // 添加3个元素到队列:
            q.offer(new User("Bob", "A1"));
            q.offer(new User("Alice", "A2"));
            q.offer(new User("Boss", "V1"));
            System.out.println(q.poll()); // Boss/V1
            System.out.println(q.poll()); // Bob/A1
            System.out.println(q.poll()); // Alice/A2
            System.out.println(q.poll()); // null,因为队列为空
        }
    }
    
    class UserComparator implements Comparator<User> {
        public int compare(User u1, User u2) {
            if (u1.number.charAt(0) == u2.number.charAt(0)) {
                // 如果两人的号都是A开头或者都是V开头,比较号的大小:
                return u1.number.compareTo(u2.number);
            }
            if (u1.number.charAt(0) == 'V') {
                // u1的号码是V开头,优先级高:
                return -1;
            } else {
                return 1;
            }
        }
    }
    
    class User {
        public final String name;
        public final String number;
    
        public User(String name, String number) {
            this.name = name;
            this.number = number;
        }
    
        public String toString() {
            return name + "/" + number;
        }
    }
    //比较比较小的先出
    

    使用Deque

    • 允许两头都进,两头都出。双端队列(Double Ended Queue) 学名Deque
    • Java集合提供了接口Deque实现一个双端队列
    Queue Deque
    添加元素到队尾 add(E e) / offer(E e) addLast(E e) / offerLast(E e)
    取队首元素并删除 E remove() / E poll() E removeFirst() / E pollFirst()
    取队首元素但不删除 E element() / E peek() E getFirst() / E peekFirst()
    添加元素到队首 addFirst(E e) / offerFirst(E e)
    取队尾元素并删除 E removeLast() / E pollLast()
    取队尾元素但不删除 E getLast() / E peekLast()

    使用Stack

    • 栈 LISO
    • 把元素压栈:push(E)
    • 把栈顶的元素“弹出”:pop(E)
    • 取栈顶元素但不弹出:peek(E)
    • Java集合类没有单独的Stack接口,只能用Deque接口来模拟一个Stack
    • 对整数进行进制的转换就可以利用栈

    使用Iterator 迭代器

    • 编译器把for each循环通过Iterator改写为普通的for循环
    for (Iterator<String> it = list.iterator(); it.hasNext(); ) {
         String s = it.next();
         System.out.println(s);
    }
    
    • 使用迭代器的好处在于,调用方总是以统一的方式遍历各种集合类型,而不必关系它们内部的存储结构
    • 集合类实现Iterable接口,该接口要求返回一个Iterator对象;
    • 用Iterator对象迭代集合内部数据。
  • 相关阅读:
    Cobar-Client 实现策略总结
    xsltproc docbook 转 html
    一个使用高并发高线程数 Server 使用异步数据库客户端造成的超时问题
    Hessian 初探
    关于 tomcat nio connector, servlet 3.0 async, spring mvc async 的关系
    Two-Phase Commit (两阶段提交)
    HashedWheelTimer 原理
    Photoshop 使用曲线
    Photoshop 使用可选颜色
    MySQL Batch 与 Transaction
  • 原文地址:https://www.cnblogs.com/chenshaowei/p/13186078.html
Copyright © 2011-2022 走看看