集合

Java标准库自带的java.util包提供了集合类:Collection

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

  • List: 有序列表的集合

  • Set: 没有重复元素

  • Map: 通过键值查找的映射表集合

集合设计的特点 1. 实现了接口和实现类相分享 如有序表的接口是List 实现类为ArrayList LinkedList 2. 支持泛型 可以在一集合中限定只放一个数据类型

Java访问集合总是通过统一的方式——迭代器(Iterator)来实现

List

使用最多为的ArrayList

  • ArrayList添加指定索引值时,自动移动

  • 添加元素,数组满时,会创建更大新数组

接口方法

  • add(e)

  • add(index, e)

  • remove(index)

  • remove(e)

  • get(index)

  • size()

//创建list
List<Integer> list = List.of(1, 2, 5);

//遍历
List<String> list = List.of("apple", "pear", "banana");
        for (String s : list) {
            System.out.println(s);
        }

//转换
Object[] array = list.toArray();

Integer[] array = list.toArray(new Integer[list.size()]);

Integer[] array = list.toArray(Integer[]::new);

通过Iterator遍历List永远是最高效的方式

map

Map中不存在重复的key,因为放入相同的key,只会把原有的key-value对应的value给替换掉。 遍历Map时,不可假设输出的key是有序的!

//创建map
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实例

//遍历key
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);
}

//遍历key-value
Map<String, Integer> map = new HashMap<>();
map.put("apple", 123);
map.put("pear", 456);
map.put("banana", 789);
for (Map.Entry<String, Integer> entry : map.entrySet()) {
    String key = entry.getKey();
    Integer value = entry.getValue();
    System.out.println(key + " = " + value);
}

hashmap

要正确使用HashMap,作为key的类必须正确覆写equals()和hashCode()方法;

一个类如果覆写了equals(),就必须覆写hashCode(),并且覆写规则是:

  • 如果equals()返回true,则hashCode()返回值必须相等;

  • 如果equals()返回false,则hashCode()返回值尽量不要相等。

实现hashCode()方法可以通过Objects.hashCode()辅助方法实现。

EnumMap

如果Map的key是enum类型,推荐使用EnumMap,既保证速度,也不浪费空间。

使用EnumMap的时候,根据面向抽象编程的原则,应持有Map接口

Map<DayOfWeek, String> map = new EnumMap<>(DayOfWeek.class);
        map.put(DayOfWeek.MONDAY, "星期一");
        map.put(DayOfWeek.TUESDAY, "星期二");
        map.put(DayOfWeek.WEDNESDAY, "星期三");
        map.put(DayOfWeek.THURSDAY, "星期四");
        map.put(DayOfWeek.FRIDAY, "星期五");
        map.put(DayOfWeek.SATURDAY, "星期六");
        map.put(DayOfWeek.SUNDAY, "星期日");
        System.out.println(map);
        System.out.println(map.get(DayOfWeek.MONDAY));
    }

TreeMap

接口是SortedMap TreeMap是实现类

  • SortedMap在遍历时严格按照Key的顺序遍历,最常用的实现类是TreeMap;

  • 作为SortedMap的Key必须实现Comparable接口,或者传入Comparator;

  • 要严格按照compare()规范实现比较逻辑,否则,TreeMap将不能正常工作

Properties

读取配置文件

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 props = new Properties();
props.setProperty("url", "http://www.liaoxuefeng.com");
props.setProperty("language", "Java");
props.store(new FileOutputStream("C:\\conf\\setting.properties"), "这是写入的properties注释");

//中文正确读取
Properties props = new Properties();
props.load(new FileReader("settings.properties", StandardCharsets.UTF_8));

用Properties读取配置文件,一共有三步:

  • 创建Properties实例;

  • 调用load()读取文件;

  • 调用getProperty()获取配置。

Java集合库提供的Properties用于读写配置文件.properties。.properties文件可以使用UTF-8编码。

可以从文件系统、classpath或其他任何地方读取.properties文件。

读写Properties时,注意仅使用getProperty()和setProperty()方法,不要调用继承而来的get()和put()等方法。

set

存储不重复的元素集合

  • 将元素添加进Set:boolean add(E e)

  • 将元素从Set删除:boolean remove(Object e)

  • 判断是否包含元素:boolean contains(Object e)

最常用的Set实现类是HashSet,实际上,HashSet仅仅是对HashMap的一个简单封装

Set接口并不保证有序,而SortedSet接口则保证元素是有序的:

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

  • TreeSet是有序的,因为它实现了SortedSet接口

Set用于存储不重复的元素集合:

  • 放入HashSet的元素与作为HashMap的key要求相同;

  • 放入TreeSet的元素与作为TreeMap的Key要求相同;

    利用Set可以去除重复元素;

  • 遍历SortedSet按照元素的排序顺序遍历,也可以自定义排序算法。

queue

Queue实际上是实现了一个先进先出(FIFO:First In First Out)的有序表 要避免把null添加到队列

它和List的区别在于,List可以在任意位置添加和删除元素,而Queue只有两个操作:

  • 把元素添加到队列末尾;

  • 从队列头部取出元素。

队列接口Queue定义了以下几个方法:

  • int size():获取队列长度;

  • boolean add(E)/boolean offer(E):添加元素到队尾;

  • E remove()/E poll():获取队首元素并从队列中删除;

  • E element()/E peek():获取队首元素但并不从队列中删除

    throw Exception

    返回false或null

    添加元素到队尾

    add(E e)

    boolean offer(E e)

    取队首元素并删除

    E remove()

    E poll()

    取队首元素但不删除

    E element()

    E peek()

    PriorityQueue

PriorityQueue实现了一个优先队列:从队首获取元素时,总是获取优先级最高的元素。

PriorityQueue默认按元素比较的顺序排序(必须实现Comparable接口),也可以通过Comparator自定义排序算法(元素就不必实现Comparable接口)。

Deque

允许两头都进,两头都出,这种队列叫双端队列(Double Ended Queue),学名Deque

Java集合提供了接口Deque来实现一个双端队列,它的功能是:

  • 既可以添加到队尾,也可以添加到队首;

  • 既可以从队首获取,又可以从队尾获取。

Deque实现了一个双端队列(Double Ended Queue),它可以:

  • 将元素添加到队尾或队首:addLast()/offerLast()/addFirst()/offerFirst();

  • 从队首/队尾获取元素并删除:removeFirst()/pollFirst()/removeLast()/pollLast();

  • 从队首/队尾获取元素但不删除:getFirst()/peekFirst()/getLast()/peekLast();

  • 总是调用xxxFirst()/xxxLast()以便与Queue的方法区分开;

  • 避免把null添加到队列。

stack

栈(Stack)是一种后进先出(LIFO)的数据结构,操作栈的元素的方法有:

  • 把元素压栈:push(E);

  • 把栈顶的元素“弹出”:pop(E);

  • 取栈顶元素但不弹出:peek(E)。

    在Java中,我们用Deque可以实现Stack的功能,注意只调用push()/pop()/peek()方法,避免调用Deque的其他方法。

最后,不要使用遗留类Stack

itertor

如果我们自己编写了一个集合类,想要使用for each循环,只需满足以下条件:

  • 集合类实现Iterable接口,该接口要求返回一个Iterator对象;

  • 用Iterator对象迭代集合内部数据。

Iterator是一种抽象的数据访问模型。使用Iterator模式进行迭代的好处有:

对任何集合都采用同一种访问模型; 调用者对集合内部结构一无所知; 集合类返回的Iterator对象知道如何迭代。 Java提供了标准的迭代器模型,即集合类实现java.util.Iterable接口,返回java.util.Iterator实例。

Collections

创建空集合 Collections提供了一系列方法来创建空集合:

  • 创建空List:List emptyList()

  • 创建空Map:Map emptyMap()

  • 创建空Set:Set emptySet()

List<String> list1 = List.of();
List<String> list2 = Collections.emptyList();

创建单元素集合 Collections提供了一系列方法来创建一个单元素集合:

  • 创建一个元素的List:List singletonList(T o)

  • 创建一个元素的Map:Map singletonMap(K key, V value)

  • 创建一个元素的Set:Set singleton(T o)

List<String> list1 = List.of("apple");
List<String> list2 = Collections.singletonList("apple");

排序

Collections.sort(list);

洗牌算法 随机打乱

Collections.shuffle(list);

可变集合 Collections还提供了一组方法把可变集合封装成不可变集合:

  • 封装成不可变List:List unmodifiableList(List<? extends T> list)

  • 封装成不可变Set:Set unmodifiableSet(Set<? extends T> set)

  • 封装成不可变Map:Map unmodifiableMap(Map<? extends K, ? extends V> m)

List<String> immutable = Collections.unmodifiableList(mutable);

Last updated

Was this helpful?