Java集合类解析

java中集合类两大分支

 - Collection 
 - Map

HashMap、Hashtable、ConcurrentHashMap特点

共同点:都实现了Map接口

HashMap特点
 - 非线程synchronized,线程不安全
 - 可存放null键、null值
 - 数组+链表数据结构
 - 初始化大小为16,加载因子0.75
Hashtable特点
 - 线程synchronized,线程安全
 - 不可存放null键、null值
LinkedHashMap特点
 - LinkedHashMap是HashMap的子类
 - 非线程synchronized,线程不安全
 - 可存放null键、null值
 - 数组+链表数据结构
ConcurrentHashMap特点
 - 线程synchronized,线程安全
 - 不可存放null键、null值
HashMap示例
HashMap<String, String> map = new HashMap<>();
        map.put("name", "xiaoming");
        map.put("", "");
        map.put(null, null);
        System.out.println("=" + map.get(null));
        map.put(null, "nihao");
        System.out.println("="+map.get(null));//当是值是null是返回null
        System.out.println("="+map.get(""));
        System.out.println("="+map.get("age"));//当没有键时返回值为null

打印结果

=null
=nihao
=
=null

总结

HashMap中不能由get()方法来判断HashMap中是否存在某个键,而应该用containsKey()方法来判断

Hashtable示例
Hashtable<String, String> table = new Hashtable<>();
table.put("", "");
System.out.println(table.get("")+"==="+table.get("ni"));

总结

Hashtable中采用的锁机制是一次锁住整个hash表,从而同一时刻只能由一个线程对其进行操作。由于Hashtable是线程安全的也是synchronized, 所以在单线程环境下它比HashMap要慢。如果你不需要同步,只需要单一线程,那么使用HashMap性能要快于Hashtable

LinkedHashMap示例
LinkedHashMap<String, String> linkedHashMap = new LinkedHashMap<>();
linkedHashMap.put(null, null);
System.out.println("linked="+linkedHashMap.get(null));

总结

LinkedHashMap是HashMap的子类,与HashMap有着同样的存储结构,但它加入了一个双向链表的头结点,将所有put到LinkedHashmap的节点按照插入的先后顺序依次加入到以head为头结点的双向循环链表的尾部。
实际上就是HashMap和LinkedList两个集合类的存储结构的结合。在LinkedHashMapMap中,所有put进来的Entry都HashMap的存储结构进行存储,但它又额外定义了一个以head为头结点的空的双向循环链表,每次put进来Entry,除了将其保存到哈希表中对应的位置上外,还要将其插入到双向循环链表的尾部。

在 LinkedHashMap 内部accessOrder标志位特点

 - 当accessOrder为false(默认),表示双向链表中的元素按照Entry插入LinkedHashMap中的先后顺序排序,每次put到LinkedHashMap中的Entry都放在双向链表的尾部
 - 当accessOrder为true时,表示双向链表中的元素按照访问的先后顺序排列,从而实现LRU算法
ConcurrentHashMap示例
ConcurrentHashMap<String, String> concurrentHashMap = new ConcurrentHashMap<>();
concurrentHashMap.put("", "");//不能存放nullnull值
System.out.println("con="+concurrentHashMap.get(""));

总结

ConcurrentHashMap中在JDK6和JDK中采用的是分段锁,只有在同一个分段内才存在竞态关系,不同的分段锁之间没有锁竞争。相比于对整个Map加锁的Hashtable设计,分段锁大大的提高了高并发环境下的处理能力。在JDK8中采用CAS(Compare-and-swap),即在不使用锁的情况下,在没有线程阻塞的情况下实现同步。这样可以避免竞态、死锁等问题。

说明:CAS是一个原子操作,用于多线程环境下的同步。它比较内存中的内容和给定的值,只有当两者相同时(说明其未被修改),才会修改内存中的内容。

SynchronizedSortedMap示例
Map<String, String> synchronizedMap = Collections.synchronizedMap(map);
        if (synchronizedMap.containsKey("name")) {
            synchronizedMap.remove("name");
        }

总结

线程A执行了containsKey方法返回true,准备执行remove操作;
这时另一个线程B开始执行,同样执行了containsKey方法返回true,并接着执行了remove操作;

然后线程A接着执行remove操作时发现此时已经没有这个元素了。显然没有按照我们的要求去执行

要保证这段代码按我们的意愿工作,一个办法就是对这段代码进行同步控制但是这么做付出的代价太大。

ArrayList、Vector、LinkedList特点

ArrayList特点
 - 基于动态数组的数据结构
 - 查询速度快(不需要移动指针)
 - 线程不安全
 - 初始化大小为10,扩容算法=(旧容量*3)/2+1
Vector特点
 - Verctor类和ArrayList的功能近乎相同
 - 线程安全
LinkedList特点
 - 基于双向循环链表数据结构
 - 添加和删除速度快(不需要移动数据)
 - 线程不安全

sleep、wait特点

sleep特点
  • sleep来自Thread类
  • sleep方法没有释放锁
  • sleep(milliseconds)可以用时间指定使它自动唤醒过来,如果时间不到只能调用interrupt()强行打断
wait特点
  • wait来自Object类
  • wait方法释放了锁
  • 要等待其他线程调用notify/notifyAll唤醒等待池中的所有线程

注意

  1. sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常
  2. sleep是Thread的静态类方法,谁调用的谁去睡觉,即使在a线程里调用b的sleep方法,实际上还是a去睡觉,要让b线程睡觉要在b的代码中调用sleep
  3. wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用
synchronized(x){ 
      x.notify() 
     //或者wait() 
   }

接口和抽象类有什么区别

相同点

  1. 抽象类和接口都不能直接实例化
  2. 抽象类里的抽象方法必须全部被子类实现,否则子类也只能是抽象类,
  3. 实现接口的类,如果不能全部实现接口方法,那该类也只能是抽象类

不同点

  1. 接口只能声明方法,抽象类可声明方法,也可实现方法(抽象类里可以没有抽象方法)
  2. 接口可继承接口,并可多继承接口,类只能单继承
  3. 抽象方法可用public、protected和default修饰符
  4. 接口方法默认修饰符是public。也不可使用其它修饰符
  5. 如果一个类有抽象方法,那这个类只能是抽象类
  6. 抽象方法需要被实现,所以不能用static修饰,也不能用private修饰

递归优缺点

优点

  1. 简洁
  2. 在树的前序,中序,后序遍历算法中,递归的实现明显要比循环简单得多

缺点

  1. 递归由于是函数调用自身,而函数调用是有时间和空间的消耗的:每一次函数调用,都需要在内存栈中分配空间以保存参数、返回地址以及临时变量,而往栈中压入数据和弹出数据都需要时间
  2. 递归中很多计算都是重复的,由于其本质是把一个问题分解成两个或者多个小问题,多个小问题存在相互重叠的部分,则存在重复计算
  3. 调用栈可能会溢出,其实每一次函数调用会在内存栈中分配空间,而每个进程的栈的容量是有限的,当调用的层次太多时,就会超出栈的容量,从而导致栈溢出
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值