Java 集合


集合是包含多个元素(数据)的容器。


常用的集合接口包括:Collection、List、Set、Map、SortedSet、SortedMap。

  • Collection接口是List和Set的父接口。
  • Set接口中的元素不能重复。
  • List接口中的元素是有顺序的,就是元素加入到List的顺序,list中的元素可以重复。
  • Map的元素是key-value对,key不能重复,可以快速根据key从Map中查询到value。
  • SortedSet以升序方式排列元素。
  • SortedMap以升序方式排列key。

遍历集合

有三种遍历集合的方式:

  • 使用for循环方式。
  • 使用Iterator接口方式。
  • 使用流的聚合函数方式。

下面是遍历集合的例子:

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class CollectionTraverse {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("apple");
        list.add("orange");

        for (String c : list)
            System.out.println(c);    // apple orange

        Iterator<String> itor = list.iterator();
        while (itor.hasNext())
            System.out.println("\t" + itor.next());    // apple orange

        list.stream().forEach(e -> System.out.println("\t\t" + e));    // apple orange
    }
}

集合和数组的转换

下面是集合和数组之间转换的例子:

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

public class CollectionArray {
    public static void main(String[] args) {
        String[] colors = new String[] {"red", "blue", "orange"};
        List<String> list = Arrays.asList(colors);

        for (String c : list)
            System.out.println(c);    // red blue orange

        String[] arr = list.toArray(new String[0]);
        for (String c : arr)
            System.out.println("\t" + c);    // red blue orange
    }
}

Set接口

常用的Set实现类有3个:

  • HashSet,保存数据在哈希表,性能很好。但在遍历时元素的顺序不确定,一般和元素加入Set时的顺序不同。
  • TreeSet,按照元素的value(值)排序。
  • LinkedHashSet,保持元素加入Set时的顺序。

下面是Set接口的例子:

import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.TreeSet;

public class CollectionSet {
    public static void main(String[] args) {
        Set<String> colors = new HashSet<>();
        colors.add("red");
        colors.add("blue");
        colors.add("red");
        colors.add("green");

        for (String c : colors)
            System.out.println(c);    // red green blue

        Set<String> fruits = new TreeSet<>();
        fruits.add("pear");
        fruits.add("apple");
        fruits.add("orange");
        for (String f : fruits)
            System.out.println("\t" + f);    // apple orange pear

        Set<String> pets = new LinkedHashSet<>();
        pets.add("dog");
        pets.add("rabbit");
        pets.add("cat");
        for (String p : pets)
            System.out.println("\t\t" + p);    // dog rabbit cat
    }
}

List接口

常用的List实现类有2个:

  • ArrayList,内部使用数组保存List的元素。读取任意位置的元素时性能好。
  • LinkedList,内部使用双向链表保存List的元素。在List的指定位置插入元素或删除List中的元素时性能好。

下面是List接口的例子:

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;

public class CollectionList {
    public static void main(String[] args) {
        List<String> colors = new ArrayList<>();
        colors.add("red");
        colors.add("blue");
        colors.add("red");

        for (String c : colors)
            System.out.println(c);    // red blue red

        List<String> fruits = new LinkedList<>();
        fruits.add("pear");
        fruits.add("apple");
        fruits.add("orange");
        ListIterator<String> itor = fruits.listIterator(fruits.size());
        // 反向遍历
        while (itor.hasPrevious())
            System.out.println("\t" + itor.previous());    // orange apple pear
    }
}

Map接口

常用的Map实现类有3个:

  • HashMap,遍历时元素的顺序不确定。
  • TreeMap,按照元素的key排序。
  • LinkedHashMap,保持元素加入Map时的顺序。

下面是Map接口的例子:

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;

public class CollectionMap {
    public static void main(String[] args) {
        Map<String, String> pets = new HashMap<>();
        pets.put("dog", "bone");
        pets.put("cat", "fish");
        pets.put("dog", "meat");
        pets.put("rabbit", "carrot");

        for (Entry<String, String> p : pets.entrySet())
            System.out.println(p.getKey() + ": " + p.getValue());    // cat: fish rabbit: carrot dog: meat

        Map<String, String> fruits = new TreeMap<>();
        fruits.put("orange", "orange");
        fruits.put("apple", "red");
        fruits.put("banana", "yellow");
        for (Entry<String, String> f : fruits.entrySet())
            System.out.println("\t" + f.getKey() + ": " + f.getValue());    // apple: red banana: yellow orange: orange

        Map<String, String> animals = new LinkedHashMap<>();
        animals.put("dog", "bark");
        animals.put("fish", "swim");
        animals.put("bird", "fly");
        for (Entry<String, String> a : animals.entrySet())
            System.out.println("\t\t" + a.getKey() + ": " + a.getValue());    // dog: bark fish: swim bird: fly
    }
}

集合排序

对集合排序,有两种方式:

  • 需要集合中的元素实现Comparable接口,通过调用Collections.sort(list)方法来对集合排序。
  • 实现Comparator接口提供对集合中元素的排序功能,通过调用Collections.sort(list, c)方法,来对集合排序,c参数为Comparator接口。

下面是集合排序使用Comparable接口的例子:

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class CollectionSort {
    public static void main(String[] args) {
        List<Fruit> fruits = new ArrayList<>();
        fruits.add(new Fruit("apple", "red"));
        fruits.add(new Fruit("orange", "orange"));
        fruits.add(new Fruit("banana", "yellow"));

        Collections.sort(fruits);
        for (Fruit f : fruits)
            System.out.println(f);    // orange: orange apple: red banana: yellow
    }
}

class Fruit implements Comparable<Fruit> {
    String name;
    String color;
    public Fruit(String name, String color) {
        this.name = name;
        this.color = color;
    }

    // 按color排序
    public int compareTo(Fruit f) {
      return color.compareTo(f.color);
  }

    public boolean equals(Object o) {
        if (!(o instanceof Fruit))
            return false;
        Fruit f = (Fruit) o;
        return f.color.equals(color);
    }

    public int hashCode() {
        return color.hashCode();
    }

    public String toString() {
        return name + ": " + color;
    }
}

下面是集合排序使用Comparator接口的例子:

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class CollectionSort2 {
    public static void main(String[] args) {
        List<Fruit> fruits = new ArrayList<>();
        fruits.add(new Fruit("apple", "red"));
        fruits.add(new Fruit("orange", "orange"));
        fruits.add(new Fruit("banana", "yellow"));

        Collections.sort(fruits, new ColorOrder());
        for (Fruit f : fruits)
            System.out.println(f);    // orange: orange apple: red banana: yellow
    }
}

class Fruit {
    String name;
    String color;
    public Fruit(String name, String color) {
        this.name = name;
        this.color = color;
    }

    public String toString() {
        return name + ": " + color;
    }
}

class ColorOrder implements Comparator<Fruit> {
    // 按color排序
    public int compare(Fruit f1, Fruit f2) {
        return f1.color.compareTo(f2.color);
    }
}

String、Date、Byte、Character、Short、Integer、Long、Double、Float、Boolean类都实现了Comparable接口,可以对这些类型的集合进行排序。