深入理解容器

Posted mgblogs

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深入理解容器相关的知识,希望对你有一定的参考价值。

Object.hasCode()默认使用对象的地址计算散列码。

Object.equals()默认比较对象地址。

一、散列与散列码

Hash结构容器散列原理(大致的原理,没有必要较真)

 技术图片

数组保存ArrayList的引用,散列码就是数组的下标值。存储元素时计算散列码,找到元素所属List,用该对象equals()方法与List中的元素比较,若发现相等元素则覆盖,没有相等元素则在空位插入。如果散列均匀,通过散列码可以急速定位List,大大减少equals()比较操作的执行次数,提高查询速度。

二、容器

1、List

ArrayList:数组实现,随机访问更快。

LinkedList:链表实现,增删数据更快。

2、Set

Set:加入Set的元素必须实现equals()接口,以确保元素的唯一性。

HashSet:(默认选择)哈希表实现,专门对快速查找进行了优化,加入HashSet的元素必须实现hashCode()方法。

LinkedHashSet:具有HashSet的查询速度,因为维持链表插入速度慢,元素必须实现hashCode()。

TreeSet:红黑树实现,保持元素次序,必须实现Comparable接口。

红黑树引用广泛,主要是用来存储有序的数据,它的时间复杂度是O(lgn),效率非常之高。

mport java.util.*;


class SetType 
    int i;
    public SetType(int n) 
        i =n;    
    
    public boolean equals(Object o) 
        return o instanceof SetType && (i == ((SetType)o).i);
     
    public String toString() 
        return String.valueOf(i);
    


class HashType extends SetType
    public HashType(int n) 
        super(n);
    
    public int hashCode() 
        return i%5;
    


class TreeType extends SetType implements Comparable<TreeType>
    public TreeType(int n) 
        super(n);
    
    public int compareTo(TreeType t) 
        return (i < t.i ? -1 : ((i == t.i) ? 0 : 1));
    

public class Demo1 
    static <T> Set<T> fill(Set<T> set, Class<T> type) 
        try 
            for(int i = 0; i < 10; i++) 
                set.add(type.getConstructor(int.class).newInstance(i));
            
        catch(Exception e) 
            throw new RuntimeException();
        
        return set;
    
    static <T> void test(Set<T> set, Class<T> type) 
        fill(set,type);
        System.out.println(set);
    
    public static void main(String[] args) 
        test(new HashSet<HashType>(), HashType.class);
        test(new TreeSet<TreeType>(), TreeType.class);
    

 输出结果:

[0, 5, 1, 6, 2, 7, 3, 8, 4, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

结果分析:通过这个简单的程序了解一下原理,真正写hashCode()和equals()时的细节还是蛮多,蛮不好写的。一般来说,实现他们都是基于对象内容的。

 

3、Map

HashMap:(默认)散列表实现,查询键快。

LinkedHashMap:链表实现,迭代更快,插入(相对HashMap)稍慢,按照插入顺序或最近最少使用顺序存储元素。

TreeMap:红黑树实现,保持次序。

三、Collections类的静态方法

 1、填充容器:

技术图片
import java.util.*;
class StringAddress 
    private String s;
    public StringAddress(String s)  this.s = s; 
    public String toString() 
        return super.toString() + " " + s;
    

public class Demo2 

    public static void main(String[] args) 
        List<StringAddress> l = new ArrayList<>(Collections.nCopies(2, new StringAddress("Hello")));
        l.add(new StringAddress("Hello"));
        System.out.println(l);
        Collections.fill(l, new StringAddress("World"));
        System.out.println(l);
    

View Code

 输出结果:

[chapter17.StringAddress@6cd8737 Hello, chapter17.StringAddress@6cd8737 Hello, chapter17.StringAddress@22f71333 Hello]
[chapter17.StringAddress@13969fbe World, chapter17.StringAddress@13969fbe World, chapter17.StringAddress@13969fbe World]

结果分析:

nCopies():填充对象的引用,返回一个不可变数组。

fill():替换已存在的元素,且不能够添加新元素。

2、动态类型安全

技术图片
import java.util.*;

class Fruit 
class Apple extends Fruit 
class Banana extends Fruit 
public class CheckedList 
    @SuppressWarnings("unchecked")
    static void oldStyleMethod(List l) 
        l.add(new Banana());
    
    public static void main(String[] args) 
        List<Apple> l1 = new ArrayList<Apple>();
        oldStyleMethod(l1);
        System.out.println(l1);
        List<Apple> l2 = Collections.checkedList(new ArrayList<Apple>(), Apple.class);
        try 
            oldStyleMethod(l2);
        catch(Exception e) 
            e.printStackTrace();
        
    

View Code

 输出结果:

[chapter17.Banana@1554909b]
java.lang.ClassCastException

结果分析:可以看到使用checkedList(),checkedMap(),checkedSet()进行类型的检查,可以防止老代码的偷梁换柱行为。

3、排序与查询

技术图片
import java.util.*;
public class Demo3 
    public static void main(String[] args) 
        String[] s = "one", "two", "three", "four", "five", "Four",
                "six", "Two";
        List<String> list = new ArrayList<String>(Arrays.asList(s));
        Collections.sort(list);
        System.out.println("sorted: " + list);
        Collections.shuffle(list);
        System.out.println("shuffle: " + list);
        Collections.sort(list, String.CASE_INSENSITIVE_ORDER);
        System.out.println("sorted-insensitive: " + list);
        int index = Collections.binarySearch(list, "Two", String.CASE_INSENSITIVE_ORDER);
        System.out.println("Location of " + "\\"Two\\" is " + index);
    
View Code

输出结果:

sorted: [Four, Two, five, four, one, six, three, two]
shuffle: [Two, Four, four, six, one, two, three, five]
sorted-insensitive: [five, Four, four, one, six, three, Two, two]
Location of "Two" is 6

结果说明:还是强调注意sort()与binarysearch()使用同样的Comparator。

4、设定不可修改的Collection或Map

技术图片
import java.util.*;
public class Demo4 

    public static void main(String[] args) 
        List<Integer> l1 = Arrays.asList(1,2,3,4);
        List<Integer> l2 = Collections.unmodifiableList(new ArrayList<Integer>(l1));
        System.out.println(l2);
        try 
            l2.set(0, 3);
        catch(Exception e) 
            e.printStackTrace();
        

    

View Code

 输出结果:

[1, 2, 3, 4]
java.lang.UnsupportedOperationException

结果说明:unmodifiableList()等方法可以创建不可修改容器。

5、其他API

技术图片
import java.util.*;
public class Demo5 

    public static void main(String[] args) 
        List<Integer> l1 = new ArrayList<Integer>();
        List<Integer> l2 = new ArrayList<Integer>();
        Collections.addAll(l1, 2,3,1,4,6,8,7,5);
        Collections.addAll(l2, 8,9,10);
        System.out.println("max: " + Collections.max(l1));
        System.out.println("min: " + Collections.min(l1));
        Collections.sort(l1);
        Collections.rotate(l1, 3);
        System.out.println("rotate: " + l1);
        System.out.println("disjoint: " + Collections.disjoint(l1, l2));
        Collections.swap(l1, 0, 7);
        System.out.println("swap: " + l1);
    

View Code

输出结果:

max: 8
min: 1
rotate: [6, 7, 8, 1, 2, 3, 4, 5]
disjoint: false
swap: [5, 7, 8, 1, 2, 3, 4, 6]

结果分析:这里列出了一部分方法

max():找最大

min():找最小

rotate():所有元素向后移动distance,后面元素循环到前面来

disjoint():两个集合没有相同元素返回true

swap():交换两个位置的元素

以上是关于深入理解容器的主要内容,如果未能解决你的问题,请参考以下文章

10张图带你深入理解Docker容器和镜像

10张图带你深入理解Docker容器和镜像

这10张图带你深入理解Docker容器和镜像

10张图带你深入理解Docker容器和镜像

深入理解DIPIoCDI以及IoC容器

Laravel Container (容器) 深入理解 (下)