数据结构之集合框架与应用

一,总体框架

哈希表那一章节又提到过具体框架,在这里好好整理一下:

图片来源:https://www.cnblogs.com/skywang12345/p/3308498.html

 集合框架是一个用来代表和操纵集合的统一架构。所有的集合框架都包含如下内容:

    接口:是代表集合的抽象数据类型。例如 Collection、List、Set、Map 等。之所以定义多个接口,是为了以不同的方式操作集合对象

    实现(类):是集合接口的具体实现。从本质上讲,它们是可重复使用的数据结构,例如:ArrayList、LinkedList、HashSet、HashMap。

    算法:是实现集合接口的对象里的方法执行的一些有用的计算,例如:搜索和排序。这些算法被称为多态,那是因为相同的方法可以在相似的接口上有着不同的实现。如工具类中的arrays和collections

除了集合,该框架也定义了几个 Map 接口和类。Map 里存储的是键/值对。尽管 Map 不是集合,但是它们完全整合在集合中。

二,大致说明

1. 在框架图中,Collection是一个接口,是高度抽象出来的集合,它包含了集合的基本操作和属性。

collection下分出来了Queue,List,Set分支。

Queue是队列的数据结构,应用场合是当需要先进先出的时候。

List是一个有序的队列,每一个元素都有它的索引。第一个元素的索引值是0。
List的实现类有LinkedList, ArrayList, Vector, Stack。

Set是一个不允许有重复元素的集合。
Set的实现类有HastSet和TreeSet。HashSet依赖于HashMap,它实际上是通过HashMap实现的;TreeSet依赖于TreeMap,它实际上是通过TreeMap实现的。他们都有的性质是不允许又重复元素。

2. Map是一个映射接口,存储key-value键值对。Map中的每一个元素包含“一个key”和“key对应的value”。

其下面的分支,

SortedMap中的内容是排序的键值对,排序的方法是通过比较器。

NavigableMap有一系列的导航方法;如"获取大于/等于某对象的键值对"、“获取小于/等于某对象的键值对”等等。

TreeMap和HashMap的区别:TreeMap实现了NavigableMap接口,表面它是有序的(默认是自然顺序,可以按照方法排定顺序),而HashMap是存储无序的键值对。

HashTable和HashMap的区别:线程安全以及速度

HashMap是非synchronized的,并可以接受null(HashMap可以接受为null的键值(key)和值(value),而Hashtable则不行)。这意味着Hashtable是线程安全的,多个线程可以共享一个Hashtable;而如果没有正确的同步的话,多个线程是不能共享HashMap的。Java 5提供了ConcurrentHashMap,它是HashTable的替代,比HashTable的扩展性更好。

另一个区别是HashMap的迭代器(Iterator)是fail-fast迭代器,而Hashtable的enumerator迭代器不是fail-fast的。所以当有其它线程改变了HashMap的结构(增加或者移除元素),将会抛出ConcurrentModificationException,但迭代器本身的remove()方法移除元素则不会抛出ConcurrentModificationException异常。但这并不是一个一定发生的行为,要看JVM。这条同样也是Enumeration和Iterator的区别。
    由于Hashtable是线程安全的也是synchronized,所以在单线程环境下它比HashMap要慢。如果你不需要同步,只需要单一线程,那么使用HashMap性能要好过Hashtable。

3. Enumeration和Iteration都是用来遍历集合的工具,vector和stack,hashtable可以用enumeration,所有的集合可以用iteration遍历集合。

4. 关于fail-fast总结

fail-fast 机制是java集合(Collection)中的一种错误机制。当多个线程对同一个集合的内容进行操作时,就可能会产生fail-fast事件。
例如:当某一个线程A通过iterator去遍历某集合的过程中,若该集合的内容被其他线程所改变了;那么线程A访问集合时,就会抛出ConcurrentModificationException异常,产生fail-fast事件。

fail-fast机制,是一种错误检测机制。它只能被用来检测错误,因为JDK并不保证fail-fast机制一定会发生。若在多线程环境下使用fail-fast机制的集合,建议使用“java.util.concurrent包下的类”去取代“java.util包下的类”。

三,具体应用

po一道关于树的遍历的题

树按级划分转化为集合

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
import java.util.*;
class Solution {
    public List<List<Integer>> levelOrderBottom(TreeNode root) {
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        List<List<Integer>> Tlist = new LinkedList<List<Integer>>();
        
        if(root == null)
            return Tlist;
        queue.offer(root);
        while(!queue.isEmpty()){
            List<Integer> subList = new LinkedList<Integer>();
            int levelNum = queue.size();
            for(int i = 0; i < levelNum; i++){
                if(queue.peek().left != null) queue.offer(queue.peek().left);
                if(queue.peek().right != null) queue.offer(queue.peek().right);
                subList.add(queue.poll().val);
            }
            Tlist.add(0,subList);
            
        }
        return Tlist;
    }
}

这道题出自于leetcode,是一道考察树的遍历的题,通过把树的节点放在队列里的过程,实现对树的遍历然后按照遍历次序确定级别,实现一个树的节点放进list的过程中。

一般关于树的知识考察会和集合框架中的数据结构相关联,树的遍历是其中的一道典型题,熟练使用框架的声明和方法,才能在题目中运用好。

猜你喜欢

转载自blog.csdn.net/wannuoge4766/article/details/85867986