- Map
- Map 接口实现特点
- Map常用方法
- Map的遍历方式
- HashMap
- Hashtable
- Properties
- 如何选取集合实现类
- TreeSet
- TreeMap
- Collections工具类
1.Map 与 Collection 并列存在。用于保存具有映射关系的数据:Key-Value(双列元素)
2.Map 中的 key 和 value 可以是任何引用类型的数据,会封装到 HashMap$Node 对象中
3.Map 中的 key 不允许重复,value 可以重复,如果key相同,value不同,那么会替换之前的value。
4.Map 的 key 可以为 null, value 也可以为 null,同样遵循以上原则。
5.key 和 value 之间存在单向一对一关系,即通过指定的 key 总能找到对应的 value
Map map = new HashMap(); map.put("null","txl"); System.out.println(map); System.out.println(map.get("null"));
Map接口的特点:
Map map = new HashMap(); map.put("no1", "韩顺平");//k-v map.put("no2", "张无忌");//k-v map.put(new Car(), new Person());//k-v //老韩解读 //1. k-v 最后是 HashMap$Node node = new Node(hash, key, value, null),Node是HaspMap的一个内部类 //2. k-v 为了方便程序员的遍历,还会 创建 EntrySet 集合 ,该集合存放的元素的类型 Entry(Entry是Map的一个静态内部类), 而一个Entry对象就有k,v EntrySetMap常用方法> 即: transient Set > entrySet; //3. entrySet 中, 定义的类型是 Map.Entry ,但是实际上存放的还是 HashMap$Node // 这时因为 static class Node implements Map.Entry //4. 当把 HashMap$Node 对象 存放到 entrySet 就方便我们的遍历, 因为 Map.Entry 提供了重要方法 // K getKey(); V getValue(); Set set = map.entrySet(); System.out.println(set.getClass());// HashMap$EntrySet for (Object obj : set) { //System.out.println(obj.getClass()); //HashMap$Node //为了从 HashMap$Node 取出k-v //1. 先做一个向下转型 Map.Entry entry = (Map.Entry) obj; System.out.println(entry.getKey() + "-" + entry.getValue() ); } Set set1 = map.keySet(); System.out.println(set1.getClass()); Collection values = map.values(); System.out.println(values.getClass());
map.put("abc","efg");//添加 map.get("abc");//根据键获取映射关系,返回的是Object int size = map.size();//获取个数 boolean bool = map.isEmpty();//判断是否为空 boolean bool2 = map.containsKey("abc");//查找键是否存在 map.clear();//清空 map.remove("abc");//根据键移除Map的遍历方式
Map map = new HashMap(); map.put("邓超","孙俪"); map.put(null,"刘亦菲"); map.put("刘令博",null); map.put("王宝强","马蓉"); map.put("鹿晗","关晓彤"); //map的遍历方式 //先取出所有的key,在通过key找到value Set set = map.keySet(); for(Object key:set){ System.out.println(key+"--"+map.get(key)); } System.out.println("---------------"); //使用迭代器 Iterator iterator = set.iterator(); while (iterator.hasNext()){ Object key = iterator.next(); System.out.println(key+"--"+map.get(key)); } System.out.println("------------"); //直接取出value Collection values = map.values(); //可以使用增强for循环或者迭代器来进行遍历 for(Object value:values){ System.out.println(value); } System.out.println("-------------"); Iterator iterator1 = values.iterator(); while (iterator1.hasNext()){ Object value = iterator1.next(); System.out.println(value);; } //第三种方法通过 EntrySet 来获取 k-v System.out.println("----------"); Set entrySet = map.entrySet(); for(Object entryset: entrySet){ Map.Entry m = (Map.Entry)entryset; System.out.println(m.getKey()+"--"+m.getValue()); } System.out.println("-----------"); Iterator iterator2 = entrySet.iterator(); while (iterator2.hasNext()){ Map.Entry m = (Map.Entry)iterator2.next(); System.out.println(m.getKey()+"--"+m.getValue()); }HashMap
HashMap没有实现同步,是线程不安全的。其它 的特点与上面的类似。
- 扩容机制[和HashSet相同],HashMap底层维护了Node类型的数组table,默认为null)当创建对象时,将加载因子(loadfactor)初始化为0.75.
- 当添加key-val时,通过key的哈希值得到在table的索引。然后判断该索引处是否有元素,如果没有元素直接添加。如果该索引处有元素,继续判断该元素的key和准备加入的key是否相等,如果相等,则直接替换val;如果不相等需要判断是树结构还是链表结构,做出相应处理。如果添加时发现容量不够,则需要扩容。
- 第1次添加,则需要扩容table容量为16,临界值(threshold)为12(16*0.75)
- 以后再扩容,则需要扩容table容量为原来的2倍(32),临界值为原来的2倍,即24,依次类推.
- 在Java8中,如果一条链表的元素个数超过TREEIFY_THRESHOLD(默认是8),并且table的大小>= MIN_TREEIFY_CAPACITY(默认64),就会进行树化(红黑树)
1)存放的元素是键值对:即K-V
- Hashtable的键和值都不能为null,否则会抛出NullPointerException
3)Hashtable使用方法基本上和HashMap一样
4)Hashtable是线程安全的(synchronized), HashMap是线程不安全的
5)Hashtable的扩容机制:
//简单说明一下Hashtable的底层 //1.底层有数组 Hashtable$Entry[]初始化大小为11 //2.临界值 threshold 8 = 11 * 0.75 //3.扩容:按照自己的扩容机制来进行即可. //4.执行方法 addEntry(hashT key,value,index); 添加K-V封装到Entry //5.当 if (count >= threshold)满足时,就进行扩容 按照int newCapacity = (oldCapacity << 1)+1的大小扩容.Properties
Properties继承自Hashtable类,并且实现了Map接口,也是使用键值对保存数据。它的使用与Hashtable基本类似,key和value也不能为空。
主要作用:Properties还可以用于从 xxx.properties文件中,加载数据到Properties类对象,并进行读取和修改
说明:工作后xoxox.properties文件通常作为配置文件,这个知识点在IO流举例
1)先判断存储的类型(一组对象[单列]或一组键值对[双列])
2)一组对象[单列]:Collection接口
允许重复:List
增删多:linkedList[底层维护了一个双向链表]
改查多:ArrayList [底层维护Object类型的可变数组]
不允许重复:Set
无序:HashSet[底层是HashMap,维护了一个哈希表即(数组+链表+红黑树)
排序:TreeSet
插入和取出顺序一致:linkedHashSet,维护数组+双向链表
3)一组键值对[双列]: Map
TreeSet键无序: HashMap[底层是:哈希表 jdk7:数组+链表,jdk8:数组+链表+红黑树]键排序:TreeMap
键插入和取出顺序一致:linkedHashMap
读取文件Properties
它的特点就是多了一个排序,但是当我们使用无参构造器时,没有排序的特点,我们可以使用一个传入比较器(匿名内部类)的构造器,按自己想要的方式排序。
public static void main(String[] args) { //按字符串的字母顺序排序 TreeSet treeSet = new TreeSet(new Comparator() { @Override public int compare(Object o1, Object o2) { return ((String)o1).compareTo((String)o2); } }); treeSet.add("abc"); treeSet.add("txl"); treeSet.add("ttt"); treeSet.add("txy"); System.out.println(treeSet); }TreeMap
它的特点也是多了一个排序,通过构造器传入一个比较器,会使得输出的结果按某种排序
TreeMap treeMap = new TreeMap(new Comparator() { @Override public int compare(Object o1, Object o2) { return ((String)o1).length()-((String)o2).length(); } }); treeMap.put("abc","tom"); treeMap.put("a","jack"); treeMap.put("ab","smith"); treeMap.put("abd","txl"); System.out.println(treeMap);
treeMap.put(“abd”,“txl”);
注意我们此时是按字符串的长度排序的,因此这个键值对的key无法插入,因为已经有了abc,只是它的值会替换掉tom.
Collections是一个 *** 作 Set、List和 Map等集合的工具类
Collections中提供了一系列静态的方法对集合元素进行排序、查询和修改等 *** 作
List list = new ArrayList(); list.add("txl"); list.add("jack"); list.add("marry"); Collections.reverse(list);//反转list中的对象 Collections.sort(list);//对list中的元素自然排序,即按照字母的顺序 Collections.shuffle(list);//对list中的元素进行随机排序 Collections.sort(list,new Comparator(){//按照指定的排序方式排序 @Override public int compare(Object o1, Object o2) { return ((String)o1).length()-((String)o2).length(); } }); Collections.swap(list,0,1);//交换两个对象的位置 Object objMax1= Collections.max(list);//按照自然排序最大的对象 Object objMax2 = Collections.max(list, new Comparator() { @Override public int compare(Object o1, Object o2) { return ((String)o1).length()-((String)o2).length(); } });//按照指定排序最大的对象 //同时还有min的方法,与max相反 int fruquency = Collections.frequency(list,"tom");//指定对象出现的次数 List list1 = new ArrayList(); for(int i = 0;i欢迎分享,转载请注明来源:内存溢出
评论列表(0条)