Java八股系列——Java数据结构

Posted _瞳孔

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java八股系列——Java数据结构相关的知识,希望对你有一定的参考价值。

如果有兴趣了解更多相关内容,欢迎来我的个人网站看看:瞳孔空间

一:Enumeration

Enumeration接口中定义了一些方法,通过这些方法可以枚举(一次获得一个)对象集合中的元素。

这种传统接口已被迭代器取代,虽然Enumeration 还未被遗弃,但在现代代码中已经被很少使用了。尽管如此,它还是使用在诸如Vector和Properties这些传统类所定义的方法中,除此之外,还用在一些API类,并且在应用程序中也广泛被使用。

public interface Enumeration<E> 
    /**
     * 判断是否为空
     */
    boolean hasMoreElements();

    /**
     * 如果此枚举对象至少还有一个可提供的元素,则返回此枚举的下一个元素。
     * 否则抛出NoSuchElementException异常。
     */
    E nextElement();

Enumeration只是接口,具体使用还得靠实现类,下面是使用示例

public class Test1 
    public static void main(String[] args) 
        Enumeration<String> days;
        Vector<String> dayNames = new Vector<>();
        dayNames.add("Sunday");
        dayNames.add("Monday");
        dayNames.add("Tuesday");
        dayNames.add("Wednesday");
        dayNames.add("Thursday");
        dayNames.add("Friday");
        dayNames.add("Saturday");
        days = dayNames.elements();
        while (days.hasMoreElements())
            System.out.println(days.nextElement());
        
    

这里采用的是Vector的elements方法返回的实现类,通过源码我们可以看到,是采用匿名内部类实现的,count就是指针,每次执行nextElement方法后指针后移,以此打印全部数据。

	protected Object[] elementData;

    E elementData(int index) 
        return (E) elementData[index];
    

    public Enumeration<E> elements() 
        return new Enumeration<E>() 
            int count = 0;

            public boolean hasMoreElements() 
                return count < elementCount;
            

            public E nextElement() 
                synchronized (Vector.this) 
                    if (count < elementCount) 
                        return elementData(count++);
                    
                
                throw new NoSuchElementException("Vector Enumeration");
            
        ;
    

二:BitSet

一个Bitset类创建一种特殊类型的数组来保存位值。BitSet中数组大小会随需要增加。这和位向量(vector of bits)比较类似。

BitSet定义了两个构造方法:


    /**
     * 无参构造,初始
     */
    public BitSet() 
        initWords(BITS_PER_WORD);
        sizeIsSticky = false;
    

    /**
     * 允许用户指定初始大小。所有位初始化为0
     */
    public BitSet(int nbits) 
        // nbits can't be negative; size 0 is OK
        if (nbits < 0)
            throw new NegativeArraySizeException("nbits < 0: " + nbits);

        initWords(nbits);
        sizeIsSticky = true;
    

下面的程序说明这个集合所支持的几种方法:

public class Test1 
    public static void main(String[] args) 
        BitSet bits1 = new BitSet(16);
        BitSet bits2 = new BitSet(16);

        // set some bits
        for(int i=0; i<16; i++) 
            if((i%2) == 0) bits1.set(i);
            if((i%5) != 0) bits2.set(i);
        
        System.out.println("Initial pattern in bits1: ");
        System.out.println(bits1);
        System.out.println("\\nInitial pattern in bits2: ");
        System.out.println(bits2);

        // AND bits
        bits2.and(bits1);
        System.out.println("\\nbits2 AND bits1: ");
        System.out.println(bits2);

        // OR bits
        bits2.or(bits1);
        System.out.println("\\nbits2 OR bits1: ");
        System.out.println(bits2);

        // XOR bits
        bits2.xor(bits1);
        System.out.println("\\nbits2 XOR bits1: ");
        System.out.println(bits2);
    

三:Vector

Vector 类实现了一个动态数组。和 ArrayList 很相似,但是两者是不同的:

  • ArrayList不是线程安全的,Vector在关键方法上都加了synchronized,是线程安全的
  • ArrayList在底层数组不够用时在原来的基础上扩展0.5倍,Vector是扩展1倍。

Vector 主要用在事先不知道数组的大小,或者只是需要一个可以改变大小的数组的情况。

Vector 类支持 4 种构造方法:

	// 创建指定大小的向量,并且增量用 incr 指定。增量表示向量每次增加的元素数目
    public Vector(int initialCapacity, int capacityIncrement) 
        super();
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        this.elementData = new Object[initialCapacity];
        this.capacityIncrement = capacityIncrement;
    

	// 创建指定大小的向量
	public Vector(int initialCapacity) 
        this(initialCapacity, 0);
    
    
    // 创建一个默认的向量,默认大小为 10
	public Vector() 
        this(10);
    
    
    // 创建一个包含集合 c 元素的向量
    public Vector(Collection<? extends E> c) 
        Object[] a = c.toArray();
        elementCount = a.length;
        if (c.getClass() == ArrayList.class) 
            elementData = a;
         else 
            elementData = Arrays.copyOf(a, elementCount, Object[].class);
        
    

下面的程序说明这个集合所支持的几种方法:

public class Test1 
    public static void main(String[] args) 
        // initial size is 3, increment is 2
        Vector v = new Vector(3, 2);
        System.out.println("Initial size: " + v.size());
        System.out.println("Initial capacity: " +
                v.capacity());
        v.addElement(1);
        v.addElement(2);
        v.addElement(3);
        v.addElement(4);
        System.out.println("Capacity after four additions: " +
                v.capacity());

        v.addElement(5.45);
        System.out.println("Current capacity: " +
                v.capacity());
        v.addElement(6.08);
        v.addElement(7);
        System.out.println("Current capacity: " +
                v.capacity());
        v.addElement((float) 9.4);
        v.addElement(10);
        System.out.println("Current capacity: " +
                v.capacity());
        v.addElement(11);
        v.addElement(12);
        System.out.println("First element: " +
                (Integer)v.firstElement());
        System.out.println("Last element: " +
                (Integer)v.lastElement());
        if(v.contains(3))
            System.out.println("Vector contains 3.");
        // enumerate the elements in the vector.
        Enumeration vEnum = v.elements();
        System.out.println("\\nElements in vector:");
        while(vEnum.hasMoreElements())
            System.out.print(vEnum.nextElement() + " ");
        System.out.println();
    

四:Stack

感觉没什么好说的

五:Dictionary

Dictionary 类是一个抽象类,用来存储键/值对,作用和Map类相似。

给出键和值,你就可以将值存储在Dictionary对象中。一旦该值被存储,就可以通过它的键来获取它。所以和Map一样, Dictionary 也可以作为一个键/值对列表。

不过Dictionary类已经过时了。在实际开发中,可以实现Map接口来获取键/值的存储功能。

public abstract
class Dictionary<K,V> 

    public Dictionary() 
    

    /**
     * 返回字典中键值对的数量
     */
    abstract public int size();

    /**
     * 判断此 dictionary 是否为空
     */
    abstract public boolean isEmpty();

    /**
     * 返回此 dictionary 中的键的枚举
     */
    abstract public Enumeration<K> keys();

    /**
     * 返回此 dictionary 中值的枚举
     */
    abstract public Enumeration<V> elements();

    /**
     * 返回此 dictionary 中该键所映射到的值
     */
    abstract public V get(Object key);

    /**
     * 将指定 key 映射到此 dictionary 中指定 value。
     */
    abstract public V put(K key, V value);

    /**
     * 从此 dictionary 中移除 key (及其相应的 value)
     */
    abstract public V remove(Object key);

六:Hashtable

Hashtable是原始的java.util的一部分, 是一个Dictionary具体的实现 。然而,Java 2 重构的Hashtable又实现了Map接口,因此,Hashtable现在集成到了集合框架中。它和HashMap类很相似,但是它支持同步。

像HashMap一样,Hashtable在哈希表中存储键/值对。当使用一个哈希表,要指定用作键的对象,以及要链接到该键的值。然后,该键经过哈希处理,所得到的散列码被用作存储在该表中值的索引。

以下是使用示例:

public class Test1 
    public static void main(String[] args) 
        // Create a hash map
        Hashtable<String, Double> balance = new Hashtable<>();
        Enumeration<String> names;
        String str;
        double bal;

        balance.put("Zara", 3434.34);
        balance.put("Mahnaz", 123.22);
        balance.put("Ayan", 1378.00);
        balance.put("Daisy", 99.22);
        balance.put("Qadir", -19.08);

        // Show all balances in hash table.
        names = balance.keys();
        while(names.hasMoreElements()) 
            str = names.nextElement();
            System.out.println(str + ": " + balance.get(str));
        
        // Deposit 1,000 into Zara's account
        bal = balance.get("Zara");
        balance.put("Zara", bal + 1000);
        System.out.println("\\nZara's new balance: " + balance.get("Zara"));
    

Hashtable 和 HashMap 的区别:

  • 线程安全性不同。HashMap线程不安全;Hashtable 中的方法是Synchronize的。
  • key、value是否允许null。HashMap的key和value都是可以是null,key只允许一个null;Hashtable的key和value都不可为null。
  • 迭代器不同。HashMap的Iterator是fail-fast迭代器;Hashtable还使用了enumerator迭代器。
  • hash的计算方式不同。HashMap计算了hash值;Hashtable使用了key的hashCode方法。
  • 默认初始大小和扩容方式不同。HashMap默认初始大小16,容量必须是2的整数次幂,扩容时将容量变为原来的2倍;Hashtable默认初始大小11,扩容时将容量变为原来的2倍加1。
  • 是否有contains方法。HashMap没有contains方法;Hashtable包含contains方法,类似于containsValue。
  • 父类不同。HashMap继承自AbstractMap;Hashtable继承自Dictionary。

七:Properties

Properties 继承于 Hashtable。表示一个持久的属性集。属性列表中每个键及其对应值都是一个字符串。

除了从 Hashtable 中所定义的方法,Properties 还定义了以下方法:

序号 方法描述
1 String getProperty(String key)
 用指定的键在此属性列表中搜索属性。
2 String getProperty(String key, String defaultProperty)
用指定的键在属性列表中搜索属性。
3 void list(PrintStream streamOut)
 将属性列表输出到指定的输出流。
4 void list(PrintWriter streamOut)
将属性列表输出到指定的输出流。
5 void load(InputStream streamIn) throws IOException
 从输入流中读取属性列表(键和元素对)。
6 Enumeration propertyNames( )
按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)。
7 Object setProperty(String key, String value)
 调用 Hashtable 的方法 put。
8 void store(OutputStream streamOut, String description)
 以适合使用  load(InputStream)方法加载到 Properties 表中的格式,将此 Properties 表中的属性列表(键和元素对)写入输出流。

使用示例如下:

public class Test1 
    public static void main(String[] args) 
        Properties capitals = new Properties();
        Set states;
        String str;

        capitals.put("Illinois", "Springfield");
        capitals.put("Missouri", "Jefferson City");
        capitals.put("Washington", "Olympia");
        capitals.put("California", "Sacramento");
        capitals.put("Indiana", "Indianapolis");

        // Show all states and capitals in hashtable.
        states = capitals.keySet(); // get set-view of keys
        Iterator itr = states.iterator();
        while(itr.hasNext()) 
            str = (String) itr.next();
            System.out.println("The capital of " +
                    str + " is " + capitals.getProperty(str) + ".");
        
        // look for state not in list -- specify default
        str = capitals.getProperty("Florida", "Not Found");
        System.out.println("\\nThe capital of Florida is " + str + ".");
    

以上是关于Java八股系列——Java数据结构的主要内容,如果未能解决你的问题,请参考以下文章

Java~大厂面试八股文~强烈推荐视频

Java八股系列——线程池拒绝策略

Java八股系列——集合框架

java八股系列——依赖注入的方式

java八股系列——spring事务失效场景

java八股系列——SpringMVC从接受请求到完成响应的过程