集合的相关知识点

Posted Camellia——

tags:

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

1.集合分为两组:单列集合(单个的对象)、双列集合(以键值对的方式存在)
2.Collection接口有两个重要的子接口List、Set,他们的实现子类都是单列集合
    1)有些可以存放重复的元素,有些不可以存放
    2)List有序,Set无序
    3)通过子接口Set和List实现的
3.Map接口的实现子类是双列集合,存放的K-V
4.List集合的特点:
    1.添加和取出的顺序一致且可以重复
    2.List集合每个元素都有其对应顺序索引,支持索引取出
5.ArrayList底层源码分析
    1.ArrayList中维护了一个Object类型的数组elementData
    2.当创建ArrayList对象时,如果使用的是无参构造,
    则初始elementData容量为0
        第一次添加,则扩容elementData为10,
        如果需要再次扩容,则扩容elementData为1.5倍
    3.如果使用指定大小的构造器,则初始化elementData容量为指定大小,
    如果需要扩容,则直接扩容elementData为1.5倍
6.Vector的基本介绍
    1.Vector底层也是一个对象数组
    2.Vector是线程同步的,即线程安全,Vector类的操作方法带有synchronized
        安全且效率不高
7.LinkedList的全面说明
    1.LinkedList底层实现了双向链表和双端队列的特点
    2.LinkedList中维护了两个属性first和last分别指向首节点和尾节点
    3.每个节点(Node对象),里面又维护了prev、next、item三个属性,其中通过pre指向前一个,通过next指向后一个节点。最终实现双向链表
    4.LinkedList的元素的添加和删除功能不是通过数组完成的,相对来说效率较高
8.    ArrayList和LinkedList(都是线程不安全的)
    1.如果我们改查的操作多,选择ArrayList
    2.如果我们增删的操作多,选择LinkedList
    3.在程序中,大部分都是查询,因此大部分情况下会选择ArrayList
9.set接口的基本介绍
    1.无序(添加和取出的顺序不一致)且取出的顺序是固定的,没有索引
    2.不允许重复元素,最多包含一个null
    3.JDK API中set的接口实现类:AbstractSet,
    ConcurrentSkipListSet, 
    CopyOnWriteArraySet, EnumSet, HashSet, 
    JobStateReasons, LinkedHashSet, TreeSet
    4.set的接口遍历方式:迭代器、增强for,不能使用索引的方式来获取
10.HashSet的特点
    1.HashSet实现了Set接口
    2.HashSet实际上是HashMap,HashMap的底层是:数组+链表+红黑树
    3.HashSet可以存放null,但是只能有一个null,即元素不能重复
    4.HashSet不保证存放元素的顺序和取出顺序一致
    5.不能有重复的元素/对象
    6.经典面试题
        set.add(new String("kk"));//ok
        set.add(new String("kk"));//加入不了
    7.HashSet的底层原理
        1.HashSet底层是HashMap
        2.添加一个元素时,先得到hash值会转成->索引值
        3.找到存储数据表table,看到这个索引位置是否已经有元素存放
        4.如果没有,直接加入
        5.如果有,调用equals比较,如果相同,就放弃添加,如果不同则添加到最后
        6.在Java8中,如果有一条链表的元素个数到达TREEIFY_THRESHOLD(默认是8)
            并且table的大小>=MIN_TREEIFY_CAPACITY(默认64)就会进树化(红黑树)
11.对HashSet的源码解读
    1.执行HashSet()
     public HashSet()
        map = new HashMap<>();
   
    2.执行add()
     public boolean add(E e)
        return map.put(e, PRESENT)==null;//PRESENT起到占位的目的,
   
    3.执行put(),该方法会执行hash(key)得到key对应的hash值,与hash算法得到的值有区别
    public V put(K key, V value) //value=PRESENT起到占位的目的,
        return putVal(hash(key), key, value, false, true);
   
    4.执行
     final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict)
        Node<K,V>[] tab; Node<K,V> p; int n, i;//定义了辅助性的变量
        //table就是HashMap的一个数组,类型是Node[]
        //if语句表示如果当前table是null,或者 大小=0,就进行一次扩容,到16
        if ((tab = table) == null || (n = tab.length) == 0)
            n = (tab = resize()).length;
        //(1)根据key得到的hash去计算key应该存放到table表的哪个索引位置
        //并把这个位置的对象赋给P
        //(2)判断P是否为null
        //(2.1)如果p为null,就表示没有存放元素,就创建一个Node
        //(2.2)就放在该位置tab[i]=newNode(hash, key, value, null)
        if ((p = tab[i = (n - 1) & hash]) == null)
            tab[i] = newNode(hash, key, value, null);
        else
            Node<K,V> e; K k;
            //如果当前索引位置对应的链表的第一个元素和准备添加的key的hash值一样
            //并且满足 下面条件之一:
            //(1)准备加入的key和P指向的Node节点的key是同一个对象
            //(2)P指向的Node节点的key的equals()和准备加入的key比较后相同
            if (p.hash == hash &&
                ((k = p.key) == key || (key != null && key.equals(k))))
                e = p;
            else if (p instanceof TreeNode)
                e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
            else
                for (int binCount = 0; ; ++binCount)
                    if ((e = p.next) == null)
                        p.next = newNode(hash, key, value, null);
                        if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                            treeifyBin(tab, hash);
                        break;
                   
                    if (e.hash == hash &&
                        ((k = e.key) == key || (key != null && key.equals(k))))
                        break;
                    p = e;
               
           
            if (e != null) // existing mapping for key
                V oldValue = e.value;
                if (!onlyIfAbsent || oldValue == null)
                    e.value = value;
                afterNodeAccess(e);
                return oldValue;
           
       
        ++modCount;
        if (++size > threshold)
            resize();
        afterNodeInsertion(evict);
        return null;
   
12.HashSet底层扩容机制和树化
    1.HashSet底层是HashMap,第一次添加时table数组扩容到16,临界值
        (threshold)16*加载因子 16*0.75=12
    2.如果table数组使用到了临界值12,就会扩容到16*2=32,新的临界值
        就是32*0.75=24,依次类推
    3.在Java8中,如果一条链表的元素个数到达TREEIFY_THRESHOLD(默认值8),
        并且table的大小>=MIN_TREEIFY_CAPACITY(默认64)就会进树化(红黑树),
        否则任然采用数组扩容机制
13.LinkedHashSet说明
    1.在LinkedHashSet底层是一个LinkedHashMap维护了一个数组和双向链表
    2.每个节点都有before和after属性,这样可以形成双向链表
    3.在添加元素时先求,hash值。在求索引,确定该元素在table位置,如果已经存在不添加
    4.同时确保插入顺序和遍历顺序的一致性,且元素不能重复
    
    
14.Map,接口实现类的特点,使用实现类HashMap
    1.Map和Collection并列存在,用于保存具有映射关系的数据Key-Value(双列元素)
    2.Map中的Key和Value可以是任何引用类型的数据,会封装到HashMap$Node对象中
    3.Map中的key不允许重复,当有相同的K,就等价于替换
    4.Map中的value是可以重复的
    5.Map中的Key和Value都可以为空,Key为空只能有一个Value为空可以有多个
    6.常用String作为Key,其他类型也可以
15.HashMap特点
    1.K-V最后存放在是HashMap$Node node=newNode(hash,key,value,null)
    2.K-V为了方便程序员的遍历,还会创建EntrySet集合,该集合存放元素的类型
        Entry,而一个Entry对象就有k,v
    3.entrySet中,定义的类型是Map.Entry,但是实际上存放的还是HashMap$Node
        因为Node实现了Map.Entry
    4.当把HashMap$Node对象存放到entrySet就方便遍历,entrySet提供
    了两个重要的方法,getKey();getValue
16.Map接口的常用方法
    remove:根据键删除映射关系
    get:根据键获取值
    size:获取元素个数
    isEmpty:判断个数是否为 0
    clear:清除 k-v
    containsKey:查找键是否存在
17.map遍历的六大方式
    public class MapFor
        public static void main(String[] args)
            Map map = new HashMap();
            map.put("刘令博", null);//OK
            map.put(null, "刘亦菲");//OK
            map.put("鹿晗", "关晓彤");//OK
            //第一组:通过key取出value值
            Set set = map.keySet();
            //        (1)增强for
            for (Object key : set)
                System.out.println(key+"=="+map.get(key));
            
            //(2)迭代器
            Iterator iterator = set.iterator();
            while (iterator.hasNext())
                Object next = iterator.next();
                System.out.println(next+"--"+map.get(next));
            
            //第二组把所有的value取出来
            Collection values = map.values();
            //        (1)增强for
            for (Object value : values)
                System.out.println(value);
            

            //        (2)迭代器
            Iterator iterator1 = values.iterator();
            while (iterator1.hasNext())
                System.out.println(iterator1.next());
            
            //第三组 :通过EntrySet  
            Set entrySet = map.entrySet();
            //1.增强for
            for (Object entry : entrySet)
                Map.Entry m=(Map.Entry)entry;
                System.out.println(m.getKey()+"**"+m.getValue());
            
            //2.迭代器
            Iterator iterator2 = entrySet.iterator();
            while(iterator2.hasNext())
                Object next = iterator2.next();
                Map.Entry m=(Map.Entry)next;
                System.out.println(m.getKey()+"&"+m.getValue());
            
        
    
18.HashMap小结
    1.Map接口的常用实现类:HashMap、Hashtable和properties
    2.HashMap经常使用
    3.HashMap以键值对的方式存取
    4.HashMap中的key不允许重复,当有相同的K,就等价于替换
    5.HashMap与HashSet一样,不保证映射顺序,因为底层是以hash表
    的方式存储的
    6.HashMap没有实现线程同步机制,因此线程不安全,方法没有做到同步互斥
19.HashMap底层机制及源码剖析
    1.HashMap底层维护了Node类型的数组table,默认为null
    2.当创建对象时,将加载因子初始化为0.75
    3.当添加k-v,如果k重复直接替换之前value的值;如果不相等判断是连败哦还是树
    做出相应的处理
    4.第一次添加,table的容量为16,临界值为12
    5.再次扩容时table的值是原来的2倍,临界值为原来的两倍
    6.在Java8中,一条链表的元素超过8个并且table的大小>=64,会进行树化
20.HashTable的基本介绍
    1.存放的元素是键值对
    2.hashtable的键和值都不能为空,否则会抛出异常,key相同时还是会替换
    3.hashTable使用方法基本上和HashMap一样
    4.hashTable是线程安全的(synchronized),hashMap是线程不安全的
21.HashTable的底层
    1.底层有数组Hashtable$Entry[]初始化大小11
    2.临界值threshold 8=11*0.75
    3.扩容:是原来大小的两倍+1
22.集合选型规则
    1.判断存储的类型(单例、双列)
    2.一组对象[单列]Collection接口
        允许重复:List
                增删多:LinkedList(底层维护了一个双向链表)
                改查多:ArrayList(底层维护了Object类型的可变数组)
        不允许重复:Set
            无序:HashSet(底层是HashMap,维护了一个哈希表(数组+链表+红黑树))
            有序:TreeSet
            插入和取出一致:LinkedHashSet,维护数组+双向链表
    3.一组键值对:Map
        键无序:HashMap(底层:哈希表jdk 7:数组+链表,jdk8:数组+链表+红黑树)
        键排序:TreeMap
        键的插入和取出顺序一致:LinkedHashMap
        读取文件:properties
23.TreeSet底层
    /*
        * 1.构造器把传入的底层对象,给到底层的TreeMap
        * 2.在底层加入 treeSet.add("b");
        *if (cpr != null) //crp就是匿名内部类对象
            do
                parent = t;
                cmp = cpr.compare(key, t.key);动态绑定compare
                if (cmp < 0)
                    t = t.left;
                else if (cmp > 0)
                    t = t.right;
                else//如果相等这个数据加入不了
                    return t.setValue(value);
            while (t != null);
       
        *
        * */
        //比较的是字符串的长度,如果长度相同则加入失败
        ((String)o1).length()-((String)o2).length()
24.TreeSet源码解读
    public class TreeMap_
    public static void main(String[] args)
        //默认无序指的是元素取出和添加的顺序不一致
        /*TreeMap treeMap = new TreeMap();*/
        TreeMap treeMap = new TreeMap(new Comparator()
            @Override
            public int compare(Object o1, Object o2)
                return ((String)o1).length()-((String)o2).length();
           
        );

        treeMap.put("ea","ds");
        treeMap.put("asd","da");
        treeMap.put("bfff","db");
        treeMap.put("cregg","dc");
        treeMap.put("egrgre","de");
        treeMap.put("ww","ds");//不是替换,直接加入不了

        /*
        * 解读源码:
        * 1.执行构造器 把传入的实现了 Comparator的匿名内部类(对象)传给了TreeMap的comparator
        * public TreeMap(Comparator<? super K> comparator)
            this.comparator = comparator;
           

           2.调用put方法
           2.1第一次添加
           *  Entry<K,V> t = root;
            if (t == null)
                compare(key, key); // type (and possibly null) check    检测是否为空

                root = new Entry<>(key, value, null);
                size = 1;
                modCount++;
                return null;
           
            2.2以后添加启用比较器
            * //决定具体的位置
            * if (cpr != null)
            do
                parent = t;
                cmp = cpr.compare(key, t.key);
                if (cmp < 0)
                    t = t.left;
                else if (cmp > 0)
                    t = t.right;
                else
                    return t.setValue(value);
            while (t != null);
       

         */
        System.out.println(treeMap);
   

25.Collections工具类
    1.Collections是一个操作Set、List、Map等集合的工具类
    2.Collections中提供了一系列静态方法对集合元素进行排序查询
    3.排序常用的方法
    reverse(List):反转 List 中元素的顺
    shuffle(List):对 List 集合元素进行随机排序
    sort(List):根据元素的自然顺序对指定 List 集合元素按升序排序
    swap(List,int, int):将指定 list 集合中的 i 处元素和 j 处元素进行交换
    4.查找替换常用的方法
    /*1) Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素
        2) Object max(Collection,Comparator):根据Comparator指定的顺序,返回给定集合中的最大元素
        3)Object min(Collection)
                4)Object min(Collection,Comparator)
        5)int frequency(Collection,Object):返回指定集合中指定元素的出现次数
        6)void copy(List destList src):将src中的内容复制到dest中
        7)boolean replaceAll(List list,Object oldValObject newVal)使用新值 替换 List 对象的所有旧值*/

    
    
    
    
    
    
    
    

javascript 相关小的知识点集合

本文主要是列出一些javascript 相关的,不限于javascript的,容易记错或者遗忘的小知识,小技巧。

1、javascript中的false

在 JavaScript,常见的 false 值:

 0, \'0\', +0, -0, false, \'\',null,undefined,NaN 

要注意空数组([])和空对象({}):

console.log([] == false) //true
console.log({} == false) //false
console.log(Boolean([])) //true
console.log(Boolean({})) //true

所以在 if 中,[] 和 {} 都表现为 true。

2、禁用js

【设置】->【显示高级设置...】->点击【隐私设置】->【内容设置】->找到 【javascript】部分

3、HBuilder编辑器(国产)

内置了Emmet

emmet给css提升

ul>li*5

a[href="www.baidu.com"]

emmet给js提升

var box=dg按下tab

ifelse用法:ife    

for循环:fori

预览快捷键:ctrl+r

字符串拼接时,选中一个变量,按\'就会在变量两边加上单引号。

4、javascript组成

ECMAScript+DOM+BOM

5、class是保留字

class是js中的保留字, 所以不允许用.class,用的都是className,比如getElementsByClassName。

6、innerHTML可以直接加标签

innerHTML里面有html标签时,会被解析成Html标签。

7、href和src和color

不用拿href和src和color取到的值做判断

pic.src这样

可以用getAttribute取。

8、控制台输出的字符串是黑色的,数字是蓝色的

    var a="11";
    var b=11;
    console.log(a);
    console.log(b); 

 

9、留言板

box.innerHtml=box.innerHtml+\'<p>\'+val+\'</p>\';

var newText=\'<p>\'+val+\'</p>\';

box.innerHtml+=newText;

10、console.dir(arr)输出集合

var arr=[\'a\',12,\'b\',\'c\',\'e\'];
    console.log(arr);
    console.dir(arr);

 

11、灵活使用Math.min()和Math.max()

Math.min(0,1,4,3)//返回最小的
0
index--;
if(index<0){
index=0;
}

可以用下面一行替代上面多行

 index=Max(0,--index);

 

 

 

 

 

 

本文作者starof,因知识本身在变化,作者也在不断学习成长,文章内容也不定时更新,为避免误导读者,方便追根溯源,请诸位转载注明出处:http://www.cnblogs.com/starof/p/6815775.html有问题欢迎与我讨论,共同进步。

以上是关于集合的相关知识点的主要内容,如果未能解决你的问题,请参考以下文章

集合类框架_List相关知识

带你整理面试过程中关于 Java 中的集合 List,Queue,Set的相关知识点

集合相关知识

Java面试题

Java开发岗面试知识点解析

JAVA容器之ArrayList集合详解