新手了解java(集合基础知识(二))-亚博电竞手机版

新手了解java,集合基础知识(二),恰卡网带你了解更多相关信息。

目录
  • 三、map
    • 1、hashmap
    • 2、treemap
    • 3.concurrenthashmap
  • 总结

三、map

​ 存储的双列元素,key是无序的,不可重复,而value是无序,可重复的。

1、hashmap

 public class hashmapdemo {     private map map = null;     public void init() {         map = new hashmap();         map.put("a", "aaa");         map.put("b", "bbb");         map.put("c", "ccc");         system.out.println(map);     }     // 添加元素     public void testput() {         // v put(k key, v value) :把指定的key和value添加到集合中         map.put("a1", "aaa");         map.put("b1", "bbb");         map.put("c1", "ccc");         system.out.println(map);         // void putall(mapm) :把指定集合添加集合中         map map1 = new hashmap();         map1.put("e", "eee");         map1.put("f", "fff");         map.putall(map1);         system.out.println(map);         // default v putifabsent(k key, v value) :如果key不存在就添加         map.putifabsent("a", "hello");         system.out.println(map);         map.putifabsent("g", "ggg");         system.out.println(map);     }     // 修改元素     public void testmodify() {         // v put(k key, v value) :把集合中指定key的值修改为指定的值         map.put("a", "hello");         map.put("a", "world");         system.out.println(map);         // 说明,当key相同时,后面的值会覆盖前面的值。         // default v replace(k key, v value) :根据key来替换值,而不做增加操作         object replace = map.replace("b1", "java");         system.out.println(replace);         system.out.println(map);         //default boolean replace(k key, v oldvalue,v newvalue)     }     // 删除元素     public void testremove() {         // v remove(object key) :根据指定key删除集合中对应的值         object c = map.remove("c");         system.out.println(c);         system.out.println(map);         // default boolean remove(object key, objectvalue) :根据key和value进行删除         map.remove("b", "bbb1");         system.out.println(map);         // void clear() :清空集合中所有元素         map.clear();         system.out.println(map);     }     // 判断元素     public void testjudge() {         // boolean isempty() :判断集合是否为空,如果是返回true,否则返回false         system.out.println(map.isempty());         // boolean containskey(object key) :判断集合中是否包含指定的key,包含返回true,否则返回false         boolean flag = map.containskey("a");         system.out.println(flag); // true         flag = map.containskey("a1");         system.out.println(flag); // false         // boolean containsvalue(object value) :判断集合中是否包含指定的value,包含返回true,否则返回false         flag = map.containsvalue("aaa");         system.out.println(flag); // true         flag = map.containsvalue("aaa1");         system.out.println(flag); // false     }     // 获取元素     public void testget() {         // int size() :返回集合的元素个数         int size = map.size();         system.out.println(size);         // v get(object key) :根据key获取值,如果找到就返回对应的值,否则返回null         object val = map.get("a");         system.out.println(val);         val = map.get("a1");         system.out.println(val); // null         // default v getordefault(object key, vdefaultvalue) :根据key获取值,如果key不存在,则返回默认值         val = map.getordefault("a1", "hello");         system.out.println(val);         // collection values() :返回集合中所有的value         collection values = map.values();         for (object value : values) {             system.out.println(value);         }         // set keyset() :返回集合中所有的key         set set = map.keyset();         for (object o : set) {             system.out.println(o);         }     }     // 迭代元素     public void testiterator() {         // 第一种:通过key获取值的方式         set keyset = map.keyset();         iterator it = keyset.iterator();         while (it.hasnext()) {             object key = it.next();             object val = map.get(key);             system.out.println(key   "="   val);         }         system.out.println("------------------------ ");         // 第二种:使用for循环         for (object key : map.keyset()) {             system.out.println(key   "="                                  map.get(key));         }         system.out.println("------------------------ ");         // 第三种:使用map接口中的内部类来完成,在框架中大量使用         set entryset = map.entryset();         for (object obj : entryset) {             map.entry entry = (map.entry) obj;             system.out.println(entry.getkey()   "="                                  entry.getvalue());         }     } } 

说明:在hashmap中键-值允许为空,但键唯一,值可重复。hashmap不是线程安全的。

2、treemap

是一个有序的集合,默认使用的是自然排序方式。

 public class person implements comparable {     private string name;     private int age;     @override     public int compareto(object o) {     if (o instanceof person) {     person p = (person) o;     return this.age - p.age;     }     return 0; }     public person() {}     public person(string name, int age) {         this.name = name;         this.age = age;     }     public int getage() {         return age;     }     public void setage(int age) {         this.age = age;     }     @override     public string tostring() {         return "person{"               "name='"   name   '\''               ", age="   age               '}';     } } 

测试

 public class teemapdemo {     @test     public void testinteger() {         treemap tm = new treemap();         tm.put(3, 333);         tm.put(2, 222);         tm.put(11, 111);         tm.put(2, 222);         system.out.println(tm);     }     @test     public void teststring() {         treemap tm = new treemap();         tm.put("hello", "hello");         tm.put("world", "world");         tm.put("about", "");         tm.put("abstract", "");         system.out.println(tm);     }     @test     public void testperson() {         treemap tm = new treemap(new comparator(){             @override             public int compare(object o1, object o2) {                 if (o1 instanceof person && o2                     instanceof person) {                     person p1 = (person) o1;                     person p2 = (person) o2;                     return p1.getage() - p2.getage();                 }                 return 0;             }         });         tm.put(new person("张三",18), null);         tm.put(new person("李四",17), null);         system.out.println(tm);     } } 

说明:从上面的代码可以发现,treemap的使用和treeset的使用非常相似,观察hashset集合的源代码可以看出,当创建 hashset集合时,其实是底层使用的是hashmap。

 public hashset() { 	map = new hashmap<>(); } 

hashset实际上存的是hashmap的key。

3.concurrenthashmap

在map集合中我们介绍了hashmaptreemap,在多线程的情况下这些集合都不是线程安全的,因此可能出现线程安全的问题。

在java中hashtable是一种线程安全的hashmaphashtable在方法上与hashmap并无区别,仅仅只是在方法使用了synchronized以此来达到线程安全的目的,我们观察hashtable的源码。

     public synchronized v get(object key) {         entry tab[] = table;         int hash = key.hashcode();         int index = (hash & 0x7fffffff) % tab.length;         for (entry e = tab[index] ; e != null ; e = e.next) {             if ((e.hash == hash) && e.key.equals(key)) {                 return (v)e.value;             }         }         return null;     } 

以上是hashtable的get源码,可以看出它仅仅只是在方法上添加了锁,这大大降低了线程的执行效率,以牺牲效率的形式来达到目的,这显然不是我们在实际中想要的,因此我们需要一种既能在线程安全方面有保障,在效率上还可以的方法。

concurrenthashmap采用的是分段锁的原理,我们观察源码。

  public v put(k key, v value) {         return putval(key, value, false);     } final v putval(k key, v value, boolean onlyifabsent) {         if (key == null || value == null) throw new nullpointerexception();         int hash = spread(key.hashcode());         int bincount = 0;         for (node[] tab = table;;) {             node f; int n, i, fh;             if (tab == null || (n = tab.length) == 0)                 tab = inittable();             else if ((f = tabat(tab, i = (n - 1) & hash)) == null) {                 if (castabat(tab, i, null,                              new node(hash, key, value, null)))                     break;                   // no lock when adding to empty bin             }             else if ((fh = f.hash) == moved)                 tab = helptransfer(tab, f);             else {                 v oldval = null;                 synchronized (f) {                     if (tabat(tab, i) == f) {                         if (fh >= 0) {                             bincount = 1;                             for (node e = f;;   bincount) {                                 k ek;                                 if (e.hash == hash &&                                     ((ek = e.key) == key ||                                      (ek != null && key.equals(ek)))) {                                     oldval = e.val;                                     if (!onlyifabsent)                                         e.val = value;                                     break;                                 }                                 node pred = e;                                 if ((e = e.next) == null) {                                     pred.next = new node(hash, key,                                                               value, null);                                     break;                                 }                             }                         }                         else if (f instanceof treebin) {                             node p;                             bincount = 2;                             if ((p = ((treebin)f).puttreeval(hash, key,                                                            value)) != null) {                                 oldval = p.val;                                 if (!onlyifabsent)                                     p.val = value;                             }                         }                     }                 }                 if (bincount != 0) {                     if (bincount >= treeify_threshold)                         treeifybin(tab, i);                     if (oldval != null)                         return oldval;                     break;                 }             }         }         addcount(1l, bincount);         return null;     } 

从源码中可以看出concurrenthashmap仅仅是在当有线程去操作当前数据的时候添加了锁,因此效率大大提高了。

在线程安全的情况下提高了效率。

总结

本篇文章就到这里了,希望能对你有所帮助,也希望您能够多多关注趣讯吧的更多内容!

展开全文
内容来源于互联网和用户投稿,文章中一旦含有亚博电竞手机版的联系方式务必识别真假,本站仅做信息展示不承担任何相关责任,如有侵权或涉及法律问题请联系亚博电竞手机版删除

最新文章

网站地图