p523-547
HashSet扩容时,只要节点到达了阈值就会扩,而不是数组长度到了才扩。
比如长16的数组,索引1放了8个,索引3放了4个,我再加一个他就会扩容。
另外谁能告诉我老师的debug界面是怎么设置的吗==忘光了
HashSet存放元素的规定
Map接口
加油啊马上就可以坦克大战了。
Map接口下存放的是双列集合!
Map接口实现类的特点[很实用]
注意:这里讲的是JDK8的Map接口特点Map_.java
1)Map与Collection并列存在。用于保存具有映射关系的数据:Key-Value
2) Map 中的key和value可以是任何引用类型的数据,会封装到HashMap$Node·对象中
3)Map中的key 不允许重复,原因和HashSet一样,前面分析过源码.
4) Map中的value可以重复
5) Map 的key 可以为null, value 也可以为null,注意key为null, 只能有一个,value 为null,可以多个.
6)常用String类作为Map的key
7) key 和 value之间存在单向一对一关系,即通过指定的key 总能找到对应的value
8)Map存放数据的key-value示意图,一对k-v是放在一个HashMap$Node中的,有因为Node 实现了Entry 接口,有些书上也说一对k-v就是一个Entry(如图)
实际上,HashMap才是本体,Set建立了一个集合Entry,指向了它。为什么可以这么搞?因为HashMap$Node implements Map.Entry,那么就可以创建一个Entry实例...
这么做是为了方便遍历
Map map = new HashMap(); map.put("no1","hso");//key-value的关系 map.put("no1","zsf"); System.out.println(map);//当有相同的key时,等价于替换。但是map中的value是可以重复的。
一句话总结:key不能重名(身份证号),value爱放啥放啥
Map遍历方式
1)containsKey:查找键是否存在
2)keySet:获取所有的key,通过key获取value
3) entrySet:获取所有关系
4)values:获取所有的值
我脑阔都是昏的
HashMap小结
1) Map接口的常用实现类:HashMap、Hashtable和Properties.
2) HashMap是 Map接口使用频率最高的实现类。
.3) HashMap是以 key-val对的方式来存储数据[案例Entry ]
4)kev不能重复,但是是值可以重复,允许使用null键建和null值。
5)如果添加相同的key,则会覆盖原来的key-val ,等同于修改.(key不会替换,val会替换)
6)与HashSet一样,(底层是数组+链表+红黑树)不保证映射的顺序,因为底层是以hash表的方式来存储的.
7) HashMap没有实现同步,因此是线程不安全的(方法没有做同步互斥操作)
HashMap底层机制及源码剖析
HashMapSource.java先说结论-》debug>扩容机制[和HashSet相同]
1) HashMap底层维护了Node类型的数组table,默认为null
2)当创建对象时,将加载因子(loadfactor)初始化为0.75.
3)当添加key-val时,通过key的哈希值得到在table的索引。然后判断该索引处是否有元素,
如果没有元素直接添加。如果该索引处有完素,继续判断该元素的key是否和准备加入的key相等,如果相等,则直接替换val;如果不相等需要判断是树结构还是链表结构,做出相应处理。如果添加时发现容量不够,则需要扩容。
4)第1次添加,则需要扩容table容量为16,临界值(threshold)为12.
5)以后再扩容,则需要扩容table容量为原来的2倍,临界值为原来的2倍,即24,依次类推.6)在Java8中,如果一条链表的元素个数超过TREEIFY_THRESHOLD(默认是8),并table的大小 >= MIN_TREEIFY_CAPACITY(默认64),就会进行树化(红黑树)
所有哈希码相同的对象会被存放在同一个桶中。在你的情况下,10个 hashCode
相同但值不同的对象将被放在同一个桶里,形成一个链表或者红黑树的节点序列。
当桶中存储的元素数量达到一定阈值(通常是8个),链表会转换为红黑树,以提高查找效率。
当你使用 HashMap
的 get
方法时,会首先计算键的哈希码,然后根据哈希码找到对应的桶。接着,会在桶中的链表或红黑树中搜索具有相同哈希码且通过 equals
方法相等的对象。
Map接口实现类-Hashtable
1)存放的元素是键值对:即 K-V
2) hashtable的键和值都不能为null,否则会抛出NullPointerException
3) hashTable使用方法基本上和HashMap一样
4)hashTable是线程安全的,hashMap是线程不安全的
5)简单看下底层结构
1.底层又一个数组,是Hashtable$Entry[ ],初始化为11,临界值11*0.75=8
2.扩容rehash()
Map接口实现类-Properties
1. Properties类继承自Hashtable类并且实现了Map接口,也是使用一种健值对的形式来保存数据。
2.他的使用特点和Hashtable类似,键和值都不能为null,否则会抛出NullPointerException
3. Properties还可以用于从xxx.properties 文件中,加载数据到Properties类对象,并进行读取和修改
4、说明:工作后x00x.properties文件通常作为配置文件,这个知识点在IO流举例,有兴趣可先看文章
如何通过key来获取value:
添加put,删除remove,修改:对应key来put,清空clear
总结
===开发中如何选择集合实现类(记住)===
在开发中,选择什么集合实现类,主要取决于业务操作特点,然后根据集合实现类特性进行选择,分析如下:
1)先判断存储的类型(一组对象或一组键值对)
2)一组对象:Collection接口
允许重复:List
增删多:LinkedList[底层维护了一个双向链表]
改查多: ArrayList[底层维护 Object类型的可变数组]
不允许重复:Set
无序:HashSet[底层是HashMap,维护了一个哈希表即(数组+链表+红黑树)】
排序:TreeSet
插入和取出顺序一致:LinkedHashSet,维护数组+双向链表
3)一组键值对:Map
键无序: HashMap [底层是:哈希表jdk7:数组+链表,jdk8:数组+链表+红黑树]
健排序:TreeMap
键插入和取出顺序一致:LinkedHashMap
读取文件Properties
TreeSet
1.当我们使用无参构造器创建TreeSet时,仍然是无序的、
2.当我们希望添加的元素,按照字符串大小来排序
使用TreeSet提供的构造器,可以传入一个比较器(匿名内部类)
TreeSet ts = new TreeSet(new Comparator() {@Overridepublic int compare(Object o1, Object o2) {Em e1 = (Em)o1;Em e2 = (Em)o2;return e1.getName().length()-e2.getName().length();} }); ts.add(new Em("madk",33,1000)); ts.add(new Em("dk",353,1000)); ts.add(new Em("mdk",8343,1000)); ts.add(new Em("k",323,1000)); System.out.println(ts);
但是这个代码不对哈!老师用的String比较的
TreeMap
和TreeSet差不多,就是多了个value可以自己设置。
修改它的compare之后(传入匿名内部类后)是按照key在比较的、
为什么不能比value?
Collections工具类
. Collections工具类介绍
1)Collections是一个操作 Set、List和Map等集合的工具类
2) Collections中提供了一系列静态的方法对集合元素进行排序、查询和修改争操作
排序操作:(均为static方法)
常用方法(一)
1) reverse(List):反转List中元素的顺序
2) shuffle(List):对List集合元素进行随机排序
3) sort(List):根据元素的自然顺序对指定List集合元素按升序排序:首字符顺序
4) sort(List,Comparator):根据指定的Comparator产生的顺序对List 集合元素进行排序(匿名内部类又来了)
5) swap(List,int,int):将指定list 集合中的i处元素和j处元素进行交换
常用方法(二)
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 dest,List src):将src中的内容复制到dest中(?你来搞笑的吗)
7) boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替换List 对象的所有旧值
终于结束了,呕