智捷社区

查看: 293|回复: 0

Java研发工程师知识点总结

[复制链接]

6

主题

6

帖子

48

积分

新手上路

Rank: 1

积分
48
发表于 2019-4-30 14:40:44 | 显示全部楼层 |阅读模式
  大纲

  一、Java基础(语言、集合框架、OOP、设计模式等)

  二、Java高级(JavaEE、框架、服务器、工具等)

  三、多线程和并发

  四、Java虚拟机

  五、数据库(Sql、MySQL、Redis等)

  六、算法与数据结构

  七、计算机网络

  八、操作系统(OS基础、Linux等)

  九、其他

  一、Java基础(语言、集合框架、OOP、设计模式等)

  1. HashMap和Hashtable的区别

  Hashtable是基于陈旧的Dictionary的Map接口的实现,而HashMap是基于哈希表的Map接口的实现

  从方法上看,HashMap去掉了Hashtable的contains方法

  HashTable是同步的(线程安全),而HashMap线程不安全,效率上HashMap更快

  HashMap允许空键值,而Hashtable不允许

  HashMap的iterator迭代器执行快速失败机制,也就是说在迭代过程中修改集合结构,除非调用迭代器自身的remove方法,否则以其他任何方式的修改都将抛出并发修改异常。而Hashtable返回的Enumeration不是快速失败的。

  注:Fast-fail机制:在使用迭代器的过程中有其它线程修改了集合对象结构或元素数量,都将抛出ConcurrentModifiedException,但是抛出这个异常是不保证的,我们不能编写依赖于此异常的程序。

  2. java的线程安全

  Vector、Stack、HashTable、ConcurrentHashMap、Properties

  3. java集合框架(常用)

  Collection - List - ArrayList

  Collection - List - LinkedList

  Collection - List - Vector

  Collection - List - Vector - Stack

  Collection - Set - HashSet

  Collection - Set - TreeSet

  Collection - List - LinkedHashSet

  Map - HashMap

  Map - TreeMap

  Map - HashTable

  Map - LinkedHashMap

  Map - ConcurrentHashMap

  3.1 List集合和Set集合

  List中元素存取是有序的、可重复的;Set集合中元素是无序的,不可重复的。

  CopyOnWriteArrayList:COW的策略,即写时复制的策略。适用于读多写少的并发场景

  Set集合元素存取无序,且元素不可重复。

  HashSet不保证迭代顺序,线程不安全;LinkedHashSet是Set接口的哈希表和链接列表的实现,保证迭代顺序,线程不安全。

  TreeSet:可以对Set集合中的元素排序,元素以二叉树形式存放,线程不安全。

  3.2 ArrayList、LinkedList、Vector的区别

  首先它们均是List接口的实现。

  ArrayList、LinkedList的区别

  1.随机存取:ArrayList是基于可变大小的数组实现,LinkedList是链接列表的实现。这也就决定了对于随机访问的get和set的操作,ArrayList要优于LinkedList,因为LinkedList要移动指针。

  2.插入和删除:LinkedList要好一些,因为ArrayList要移动数据,更新索引。

  3.内存消耗:LinkedList需要更多的内存,因为需要维护指向后继结点的指针。

  Vector从JDK 1.0起就存在,在1.2时改为实现List接口,功能与ArrayList类似,但是Vector具备线程安全。

  3.3 Map集合

  Hashtable:基于Dictionary类,线程安全,速度快。底层是哈希表数据结构。是同步的。 不允许null作为键,null作为值。

  Properties:Hashtable的子类。用于配置文件的定义和操作,使用频率非常高,同时键和值都是字符串。

  HashMap:线程不安全,底层是数组加链表实现的哈希表。允许null作为键,null作为值。HashMap去掉了contains方法。 注意:HashMap不保证元素的迭代顺序。如果需要元素存取有序,请使用LinkedHashMap

  TreeMap:可以用来对Map集合中的键进行排序。

  ConcurrentHashMap:是JUC包下的一个并发集合。

  3.4 为什么使用ConcurrentHashMap而不是HashMap或Hashtable?

  HashMap的缺点:主要是多线程同时put时,如果同时触发了rehash操作,会导致HashMap中的链表中出现循环节点,进而使得后面get的时候,会死循环,CPU达到100%,所以在并发情况下不能使用HashMap。让HashMap同步:Map m = Collections.synchronizeMap(hashMap);而Hashtable虽然是同步的,使用synchronized来保证线程安全,但在线程竞争激烈的情况下HashTable的效率非常低下。因为当一个线程访问HashTable的同步方法时,其他线程访问HashTable的同步方法时,可能会进入阻塞或轮询状态。如线程1使用put进行添加元素,线程2不但不能使用put方法添加元素,并且也不能使用get方法来获取元素,所以竞争越激烈效率越低。

  ConcurrentHashMap的原理:

  HashTable容器在竞争激烈的并发环境下表现出效率低下的原因在于所有访问HashTable的线程都必须竞争同一把锁,那假如容器里有多把锁,每一把锁用于锁容器其中一部分数据,那么当多线程访问容器里不同数据段的数据时,线程间就不会存在锁竞争,从而可以有效的提高并发访问效率,这就是ConcurrentHashMap所使用的锁分段技术,首先将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问。

  ConcurrentHashMap的结构:

  ConcurrentHashMap是由Segment数组结构和HashEntry数组结构组成。Segment是一种可重入互斥锁ReentrantLock,在ConcurrentHashMap里扮演锁的角色,HashEntry则用于存储键值对数据。一个ConcurrentHashMap里包含一个Segment数组,Segment的结构和HashMap类似,是一种数组和链表结构, 一个Segment里包含一个HashEntry数组,每个HashEntry是一个链表结构的元素,当对某个HashEntry数组的数据进行修改时,必须首先获得它对应的Segment锁。

  ConcurrentHashMap的构造、get、put操作:

  构造函数:传入参数分别为 1、初始容量,默认16 2、装载因子 装载因子用于rehash的判定,就是当ConcurrentHashMap中的元素大于装载因子*最大容量时进行扩容,默认0.75 3、并发级别 这个值用来确定Segment的个数,Segment的个数是大于等于concurrencyLevel的第一个2的n次方的数。比如,如果concurrencyLevel为12,13,14,15,16这些数,则Segment的数目为16(2的4次方)。默认值为static final int DEFAULT_CONCURRENCY_LEVEL = 16;。理想情况下ConcurrentHashMap的真正的并发访问量能够达到concurrencyLevel,因为有concurrencyLevel个Segment,假如有concurrencyLevel个线程需要访问Map,并且需要访问的数据都恰好分别落在不同的Segment中,则这些线程能够无竞争地自由访问(因为他们不需要竞争同一把锁),达到同时访问的效果。这也是为什么这个参数起名为“并发级别”的原因。默认16.

  初始化的一些动作:

  初始化segments数组(根据并发级别得到数组大小ssize),默认16

  初始化segmentShift和segmentMask(这两个全局变量在定位segment时的哈希算法里需要使用),默认情况下segmentShift为28,segmentMask为15

  初始化每个Segment,这一步会确定Segment里HashEntry数组的长度.

  put操作:

  1、判断value是否为null,如果为null,直接抛出异常。

  2、key通过一次hash运算得到一个hash值。将得到hash值向右按位移动segmentShift位,然后再与segmentMask做&运算得到segment的索引j。即segmentFor方法

  3、使用Unsafe的方式从Segment数组中获取该索引对应的Segment对象。向这个Segment对象中put值,这个put操作也基本是一样的步骤(通过&运算获取HashEntry的索引,然后set)。

  get操作:

  1、和put操作一样,先通过key进行hash确定应该去哪个Segment中取数据。

  2、使用Unsafe获取对应的Segment,然后再进行一次&运算得到HashEntry链表的位置,然后从链表头开始遍历整个链表(因为Hash可能会有碰撞,所以用一个链表保存),如果找到对应的key,则返回对应的value值,如果链表遍历完都没有找到对应的key,则说明Map中不包含该key,返回null。

  定位Segment的hash算法:(hash >>> segmentShift) & segmentMask

  定位HashEntry所使用的hash算法:int index = hash & (tab.length - 1);

  注:

  1.tab为HashEntry数组

  2.ConcurrentHashMap既不允许null key也不允许null value

  3.5 Collection 和 Collections的区别

  Collection是集合类的上级接口,子接口主要有Set 和List、Queue Collections是针对集合类的一个辅助类,提供了操作集合的工具方法:一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作。

  3.6 Map、Set、List、Queue、Stack的特点与用法

  Set集合类似于一个罐子,"丢进"Set集合里的多个对象之间没有明显的顺序。 List集合代表元素有序、可重复的集合,集合中每个元素都有其对应的顺序索引。 Stack是Vector提供的一个子类,用于模拟"栈"这种数据结构(LIFO后进先出) Queue用于模拟"队列"这种数据结构(先进先出 FIFO)。 Map用于保存具有"映射关系"的数据,因此Map集合里保存着两组值。

  3.7 HashMap的工作原理

  HashMap维护了一个Entry数组,Entry内部类有key,value,hash和next四个字段,其中next也是一个Entry类型。可以将Entry数组理解为一个个的散列桶。每一个桶实际上是一个单链表。当执行put操作时,会根据key的hashcode定位到相应的桶。遍历单链表检查该key是否已经存在,如果存在,覆盖该value,反之,新建一个新的Entry,并放在单链表的头部。当通过传递key调用get方法时,它再次使用key.hashCode()来找到相应的散列桶,然后使用key.equals()方法找出单链表中正确的Entry,然后返回它的值。

  3.8 Map的实现类的介绍

  HashMap基于散列表来的实现,即使用hashCode()进行快速查询元素的位置,显著提高性能。插入和查询“键值对”的开销是固定的。可以通过设置容量和装载因子,以调整容器的性能。

  LinkedHashMap, 类似于HashMap,但是迭代遍历它时,保证迭代的顺序是其插入的次序,因为它使用链表维护内部次序。此外可以在构造器中设定LinkedHashMap,使之采用LRU算法。使没有被访问过的元素或较少访问的元素出现在前面,访问过的或访问多的出现在后面。这对于需要定期清理元素以节省空间的程序员来说,此功能使得程序员很容易得以实现。

  TreeMap, 是基于红黑树的实现。同时TreeMap实现了SortedMap接口,该接口可以确保键处于排序状态。所以查看“键”和“键值对”时,所有得到的结果都是经过排序的,次序由自然排序或提供的Comparator决定。SortedMap接口拥有其他额外的功能,如:返回当前Map使用的Comparator比较强,firstKey(),lastKey(),headMap(toKey),tailMap(fromKey)以及可以返回一个子树的subMap()方法等。

  WeakHashMap,表示弱键映射,WeakHashMap 的工作与正常的 HashMap 类似,但是使用弱引用作为 key,意思就是当 key 对象没有任何引用时,key/value 将会被回收。

  ConcurrentHashMap, 在HashMap基础上分段锁机制实现的线程安全的HashMap。

  IdentityHashMap 使用==代替equals() 对“键”进行比较的散列映射。专为解决特殊问题而设计。

  HashTable:基于Dictionary类的Map接口的实现,它是线程安全的。

  3.9 LinkedList 和 PriorityQueue 的区别

  它们均是Queue接口的实现。拥有FIFO的特点,它们的区别在于排序行为。LinkedList 支持双向列表操作, PriorityQueue 按优先级组织的队列,元素的出队次序由元素的自然排序或者由Comparator比较器指定。

  3.10 线程安全的集合类。Vector、Hashtable、Properties和Stack、ConcurrentHashMap

  3.11 BlockingQueue

  Java.util.concurrent.BlockingQueue是一个队列,在进行获取元素时,它会等待队列变为非空;当在添加一个元素时,它会等待队列中的可用空间。BlockingQueue接口是Java集合框架的一部分,主要用于实现生产者-消费者模式。我们不需要担心等待生产者有可用的空间,或消费者有可用的对象,因为它都在BlockingQueue的实现类中被处理了。Java提供了集中BlockingQueue的实现,比如ArrayBlockingQueue、LinkedBlockingQueue、PriorityBlockingQueue,、SynchronousQueue等。

  3.12 如何对一组对象进行排序

  如果需要对一个对象数组进行排序,我们可以使用Arrays.sort()方法。如果我们需要排序一个对象列表,我们可以使用Collections.sort()方法。排序时是默认根据元素的自然排序(使用Comparable)或使用Comparator外部比较器。Collections内部使用数组排序方法,所有它们两者都有相同的性能,只是Collections需要花时间将列表转换为数组。

  4. ArrayList

  无参构造 容量为10

  ArrayList(Collections<?extends E> c)构造包含指定collection的元素的列表

  ArrayList(int initialCapacity) 指定初始容量

  5. final关键字

  final修饰的变量是常量,必须进行初始化,可以显示初始化,也可以通过构造进行初始化,如果不初始化编译会报错。

  6. 接口与抽象类

  6.1 一个子类只能继承一个抽象类,但能实现多个接口 6.2 抽象类可以有构造方法,接口没有构造方法 6.3 抽象类可以有普通成员变量,接口没有普通成员变量 6.4 抽象类和接口都可有静态成员变量,抽象类中静态成员变量访问类型任意,接口只能public static final(默认) 6.5 抽象类可以没有抽象方法,抽象类可以有普通方法,接口中都是抽象方法 6.6 抽象类可以有静态方法,接口不能有静态方法 6.7 抽象类中的方法可以是public、protected;接口方法只有public abstract

  7. 抽象类和最终类

  抽象类可以没有抽象方法, 最终类可以没有最终方法

  最终类不能被继承, 最终方法不能被重写(可以重载)

  8.异常

  相关的关键字 throw、throws、try...catch、finally

  throws 用在方法签名上, 以便抛出的异常可以被调用者处理

  throw 方法内部通过throw抛出异常

  try 用于检测包住的语句块, 若有异常, catch子句捕获并执行catch块

  9. 关于finally

  finally不管有没有异常都要处理

  当try和catch中有return时,finally仍然会执行,finally比return先执行

  不管有木有异常抛出, finally在return返回前执行

  finally是在return后面的表达式运算后执行的(此时并没有返回运算后的值,而是先把要返回的值保存起来,管finally中的代码怎么样,返回的值都不会改变,仍然是之前保存的值),所以函数返回值是在finally执行前确定的

  注意:finally中最好不要包含return,否则程序会提前退出,返回值不是try或catch中保存的返回值

网上内容付费app都有哪些?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|智捷社区 ( 京ICP备09013343号-1

GMT+8, 2019-8-26 03:54 , Processed in 0.069759 second(s), 24 queries .

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表