Java中Collection和Map体系(Java容器)

Java中Collection和Map体系(Java容器)

Java常用容器类继承关系图解

Java中Collection和Map体系(Java容器)_第1张图片

Java中Collection和Map体系(Java容器)_第2张图片

Java容器类简介

Java中容器类主要分为四中体系:ListSetQueueMap

List:代表有序、可重复的集合;
Set:代表无序、不可重复的集合;
Queue:代表一种队列集合实现;
Map:代表具有映射关系的集合。

容器简介

Collection:Collection体系中的基本接口,没有直接实现类,只有子接口(包含ListSetQueue接口等);定义了对集合的基本操作方法(增、删、改、查、遍历、获取集合大小等);
List:是一个有序的 Collection,使用此接口能够精确的控制每个元素插入的位置,能够通过索引(元素在List中位置,类似于数组的下标)来访问List中的元素,第一个元素的索引为 0,而且允许有相同的元素;List 接口存储一组不唯一,有序(插入顺序)的对象。
Set:Set集合与Collection集合基本相同,没有提供其他额外的方法。实际上Set就是Collection,只是行为略有不同;Set 接口存储一组唯一,无序的对象。
Queue:Queue表示队列这种数据结构,队列通常是指**“先进先出”(FIFO,first-in-first-out)的容器**。新元素插入(offer)到队列的尾部,访问元素(poll)操作会返回队列头部的元素。通常,队列不允许随机访问队列中的元素。
Stack:Stack表示栈结构。与队列(Queue)不同,它实现了一个标准的**“后进先出”(LIFO,last-in-first-out)的容器**。
Map:Map 接口存储一组键值对对象,提供key(键)到value(值)的映射。key和value之间存在单向一对一关系,即通过指定的key,总能找到唯一的、确定的value。从Map中取出数据时,只要给出指定的key,就可以取出对应的value,Map的key不能重复,如果重复添加,会覆盖原来的值。

容器的元素存取与遍历

List

存取元素

List list = new ArrayList<>();

// 增加元素
list.add("BB");
list.add("CC");
list.add(0, "AA");

// 根据索引获取值
String value = list.get(0);

遍历

List list = new ArrayList<>();

// 增加元素
list.add("AA");
list.add("BB");
list.add("CC");

// 方式1:使用foreach遍历List,推荐
System.out.println("使用foreach遍历List:");
for (String str : list) {            //也可以改写for(int i=0;i iterator = list.iterator();
while (iterator.hasNext()) { //判断下一个元素之后有值
    System.out.println(iterator.next());
}

Set

存取元素

Set set = new HashSet<>();

// 添加元素
set.add("AA");
set.add("BB");
set.add("CC");
// set 集合没有提供快速取出指定位置或者指定元素的方法
// 只能遍历取值,或者将set集合转换为list集合,在使用list集合的方法取数据

遍历

Set set = new HashSet<>();

// 添加元素
set.add("AA");
set.add("BB");
set.add("CC");


// 方式1:使用foreach遍历set,推荐
System.out.println("使用foreach遍历Set:");
for (String str : set) {            // 没有 for(int i=0;i iterator = set.iterator();
while (iterator.hasNext()) { //判断下一个元素之后有值
    System.out.println(iterator.next());
}

// 方式4:变为List集合后使用操作
List list = new ArrayList<>(set);
System.out.println(list);

Map

存取元素

Map map = new HashMap<>();

// 添加元素
map.put(1,"AA");
map.put(2,"BB");
map.put(3,"CC");
// 根据 key 获取 value
String value = map.get(1);

遍历

Map map = new HashMap<>();
// 添加元素
map.put(1, "AA");
map.put(2, "BB");
map.put(3, "CC");

// 方式1
System.out.println("通过Map.keySet遍历key和value:");
for (Integer integer : map.keySet()) {
    String value = map.get(integer);
    System.out.println("key=" + integer + "; value=" + value);
}

// 方式2,推荐
System.out.println("通过Map.entrySet遍历key和value:");
for (Map.Entry integerStringEntry : map.entrySet()) {
    System.out.println("key=" + integerStringEntry.getKey() + "; value=" + integerStringEntry.getValue());
}

// 方式3
System.out.println("通过Map.entrySet使用iterator遍历key和value:");
Iterator> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
    Map.Entry entry = iterator.next();
    System.out.println("key=" + entry.getKey() + "; value=" + entry.getValue());
}

// 方式4,只能遍历value
System.out.println("通过Map.values()遍历所有的value,但不能遍历key:");
for (String value : map.values()) {
    System.out.println("value=" + value);
}

Queue

存取元素

 Queue queue = new ArrayDeque<>();

queue.add("AA");
queue.offer("BB");
queue.offer("CC");
queue.offer("DD");

System.out.println(queue);
String element = queue.element(); // 获取,但是不移除此队列的头
String peek = queue.peek(); // 获取但不移除此队列的头;如果此队列为空,则返回 null
String remove = queue.remove(); // 获取并移除此队列的头
String poll = queue.poll(); // 获取并移除此队列的头,如果此队列为空,则返回 null

System.out.println("element: " + element + " peek: " + peek + " remove: " + remove + " poll: " + poll);
System.out.println(queue); 

遍历元素

Queue queue = new ArrayDeque<>();
queue.add("AA");
queue.offer("BB");
queue.offer("CC");
queue.offer("DD");

// 方式1:集合方式遍历,元素不会被移除
System.out.println("集合方式遍历,元素不会被移除: ");
for (String string : queue) {
    System.out.println(string);
}

// 方式2:队列方式遍历,元素逐个被移除
System.out.println("队列方式遍历,元素逐个被移除: ");
while (queue.peek() != null) {
    System.out.println(queue.poll());
}

Stack

存取元素

Stack stringStack = new StringStack();
stringStack.add("AA");
stringStack.push("BB");
stringStack.push("CC");
stringStack.push("DD");

System.out.println(stringStack);
String peek = stringStack.peek(); // 查看堆栈顶部的对象,但不从堆栈中移除它
String pop = stringStack.pop();   // 移除堆栈顶部的对象,并作为此函数的值返回该对象
System.out.println("peek: " + peek + " pop: " + pop);

遍历

Stack stringStack = new StringStack();
stringStack.add("AA");
stringStack.push("BB");
stringStack.push("CC");
stringStack.push("DD");

// 方式1:集合遍历方式
System.out.println("集合遍历方式: ");
for (String string : stringStack) {
    System.out.println(string);
}
// 方式2:栈弹出遍历方式
System.out.println("栈弹出遍历方式: ");
while (!stringStack.empty()){
    System.out.println(stringStack.pop());
}

线程安全/线程不安全集合

Java 中常见的线程安全的集合:
Vector:就比ArrayList多了个同步化机制(线程安全),因为效率较低,现在已经不太建议使用
Statck:栈,继承Vector,先进后出(LIFO)
Hashtable:就比HashMap多了个线程安全
将线程不安全的集合变为线程安全的集合:
使用 Collections.synchronizedXxx() 方法

List list = new ArrayList<>();
Set set = new HashSet<>();
Map map = new HashMap<>();
// 将线程不安全集合变为线程安全集合
List synchronizedList = Collections.synchronizedList(list);
Set synchronizedSet = Collections.synchronizedSet(set);
Map synchronizedMap = Collections.synchronizedMap(map);
// ...

使用比较器对元素自定义排序

Comparable和Comparator接口都是为了对类进行比较,众所周知,诸如Integer,double等基本数据类型,java可以对他们进行比较,而对于类的比较,需要人工定义比较用到的字段比较逻辑。可以把Comparable理解为内部比较器,而Comparator是外部比较器,基本的写法如下:

使用 Comparable 排序

// 定义实体类
public class UserA implements Comparable {
    public String name;
    public int age;

    public UserA(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public int compareTo(UserA o) {
        return this.age - o.age;
    }

    @Override
    public String toString() {
        return "UserA{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

// 使用排序
public void comparableTest(){
    List list = new ArrayList<>();
    list.add(new UserA("张三",23));
    list.add(new UserA("李四",22));
    list.add(new UserA("王五",25));

    System.out.println("before: " + list);
    Collections.sort(list);
    System.out.println("after: " + list);
}

使用 Comparator 排序

// 定义实体类
public class UserB{
    public String name;
    public int age;

    public UserB(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "UserA{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

// 使用排序
public void comparatorTest(){
    List list = new ArrayList<>();
    list.add(new UserB("张三",23));
    list.add(new UserB("李四",22));
    list.add(new UserB("王五",25));

    System.out.println("before: " + list);
    Collections.sort(list, new Comparator() {
        @Override
        public int compare(UserB o1, UserB o2) {
            return o1.age - o2.age;
        }
    });
    System.out.println("after: " + list);
}

Java集合和数组的区别

  1. 数组的长度在初始化时就已经固定,也就是说只能保存固定长度的数据。而集合的长度是可以动态变化的,所以可以保存数量不确定的数据。
  2. 数组元素即可以是基本类型,也可以是对象。集合里只能保存对象(实际上只是保存对象的引用变量),基本数据类型的值要转换成对应的包装类才能放入集合类中。

你可能感兴趣的:(Java知识)