diff --git a/code/src/main/java/com/raorao/java/Test.java b/code/src/main/java/com/raorao/java/Test.java index ab53b1ac..d1774164 100644 --- a/code/src/main/java/com/raorao/java/Test.java +++ b/code/src/main/java/com/raorao/java/Test.java @@ -1,9 +1,39 @@ package com.raorao.java; +import com.google.common.collect.HashBasedTable; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.Map.Entry; + public class Test { + static int a; - int b; static int c; + int b; + + public static int cMethod() { + c++; + return c; + } + + public static void main(String args[]) { + Hashtable hashMap = new Hashtable<>(); + hashMap.put(1, 10); + hashMap.put(2, 20); + hashMap.put(3, 30); + hashMap.put(19, 30); + hashMap.forEach((e1, e2)-> System.out.println( e1 + ":" + e2)); + Iterator> iterator = hashMap.entrySet().iterator(); + Enumeration enumeration = hashMap.elements(); + while (enumeration.hasMoreElements()){ + System.out.println(enumeration.nextElement()); + } + + } public int aMethod() { a++; @@ -14,15 +44,4 @@ public class Test { b++; return b; } - - public static int cMethod() { - c++; - return c; - } - - public static void main(String args[]) { - String str = null; - - System.out.println(str); - } } \ No newline at end of file diff --git a/code/src/main/java/com/raorao/java/althorithm/HeapSort.java b/code/src/main/java/com/raorao/java/althorithm/HeapSort.java new file mode 100644 index 00000000..8f8f8a7e --- /dev/null +++ b/code/src/main/java/com/raorao/java/althorithm/HeapSort.java @@ -0,0 +1,70 @@ +package com.raorao.java.althorithm; + +import java.util.Arrays; + +/** + * 堆排序. + * + * 参考链接:https://www.cnblogs.com/chengxiao/p/6129630.html + * + * @author Xiong Raorao + * @since 2018-08-15-19:19 + */ +public class HeapSort { + + public static void main(String[] args) { + int []arr = {4,6,8,5,9}; + sort(arr); + System.out.println(Arrays.toString(arr)); + } + + public static void sort(int []arr){ + //1.构建大顶堆 + for(int i=arr.length/2-1;i>=0;i--){ + //从第一个非叶子结点从下至上,从右至左调整结构 + adjustHeap(arr,i,arr.length); + } + //2.调整堆结构+交换堆顶元素与末尾元素 + for(int j=arr.length-1;j>0;j--){ + swap(arr,0,j);//将堆顶元素与末尾元素进行交换 + adjustHeap(arr,0,j);//重新对堆进行调整,每调整好一个,length就减少一个。 + } + + } + + /** + * 调整大顶堆(仅是调整过程,建立在大顶堆已构建的基础上) + * @param arr + * @param i + * @param length + */ + public static void adjustHeap(int []arr,int i,int length){ + int temp = arr[i];//先取出当前元素i + for(int k=i*2+1;ktemp){//如果子节点大于父节点,将子节点值赋给父节点(不用进行交换) + arr[i] = arr[k]; + i = k; + }else{ + break; + } + } + arr[i] = temp;//将temp值放到最终的位置 + } + + /** + * 交换元素 + * @param arr + * @param a + * @param b + */ + public static void swap(int []arr,int a ,int b){ + int temp=arr[a]; + arr[a] = arr[b]; + arr[b] = temp; + } + + +} diff --git a/interview/answer.md b/interview/answer.md new file mode 100644 index 00000000..087755ea --- /dev/null +++ b/interview/answer.md @@ -0,0 +1,86 @@ + + +- [java基础](#java基础) + - [java 语言基础](#java-语言基础) + - [java自动拆装箱:](#java自动拆装箱) + - [java 四种引用及其应用场景](#java-四种引用及其应用场景) + - [foreach与正常for循环效率对比](#foreach与正常for循环效率对比) + - [java反射的作用于原理](#java反射的作用于原理) +- [数据库](#数据库) + - [truncate与 delete区别](#truncate与-delete区别) + - [B+树索引和哈希索引的区别](#b树索引和哈希索引的区别) + + + +# java基础 + +## java 语言基础 + +### java自动拆装箱: + +自动装箱是将一个java定义的基本数据类型赋值给相应封装类的变量。 拆箱与装箱是相反的操作,自动拆箱则是将一个封装类的变量赋值给相应基本数据类型的变量。 + +### java 四种引用及其应用场景 + +1、强引用 +最普遍的一种引用方式,如String s = "abc",变量s就是字符串“abc”的强引用,只要强引用存在,则垃圾回收器就不会回收这个对象。 + +2、软引用(SoftReference) +用于描述还有用但非必须的对象,如果内存足够,不回收,如果内存不足,则回收。一般用于实现内存敏感的高速缓存,软引用可以和引用队列ReferenceQueue联合使用,如果软引用的对象被垃圾回收,JVM就会把这个软引用加入到与之关联的引用队列中。 + +3、弱引用(WeakReference) +弱引用和软引用大致相同,弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。 + +4、虚引用(PhantomReference) +就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。 虚引用主要用来跟踪对象被垃圾回收器回收的活动。 + + +虚引用与软引用和弱引用的一个区别在于: +虚引用必须和引用队列 (ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。 + +### foreach与正常for循环效率对比 + +用for循环arrayList 10万次花费时间:5毫秒。 +用foreach循环arrayList 10万次花费时间:7毫秒。 +用for循环linkList 10万次花费时间:4481毫秒。 +用foreach循环linkList 10万次花费时间:5毫秒。 +循环ArrayList时,普通for循环比foreach循环花费的时间要少一点。 +循环LinkList时,普通for循环比foreach循环花费的时间要多很多。 +当我将循环次数提升到一百万次的时候,循环ArrayList,普通for循环还是比foreach要快一点;但是普通for循环在循环LinkList时,程序直接卡死。 +ArrayList:ArrayList是采用数组的形式保存对象的,这种方式将对象放在连续的内存块中,所以插入和删除时比较麻烦,查询比较方便。 +LinkList:LinkList是将对象放在独立的空间中,而且每个空间中还保存下一个空间的索引,也就是数据结构中的链表结构,插入和删除比较方便,但是查找很麻烦,要从第一个开始遍历。 + +结论: +**需要循环数组结构的数据时,建议使用普通for循环,因为for循环采用下标访问,对于数组结构的数据来说,采用下标访问比较好。 +需要循环链表结构的数据时,一定不要使用普通for循环,这种做法很糟糕,数据量大的时候有可能会导致系统崩溃。** + +链表:使用foreach +数组:使用for循环 + +### java反射的作用于原理 + +Java 反射是可以让我们在运行时,通过一个类的Class对象来获取它获取类的方法、属性、父类、接口等类的内部信息的机制。 + +这种动态获取信息以及动态调用对象的方法的功能称为JAVA的反射。 + +# 数据库 + +## truncate与 delete区别 + +TRUNCATE TABLE 在功能上与不带 WHERE 子句的 DELETE 语句相同:二者均删除表中的全部行。但 TRUNCATE TABLE 比 DELETE 速度快,且使用的系统和事务日志资源少。 DELETE 语句每次删除一行,并在事务日志中为所删除的每行记录一项。 +TRUNCATE TABLE 通过释放存储表数据所用的数据页来删除数据,并且只在事务日志中记录页的释放。 TRUNCATE,DELETE,DROP 放在一起比较: +TRUNCATE TABLE :删除内容、释放空间但不删除定义。 +DELETE TABLE: 删除内容不删除定义,不释放空间。 +DROP TABLE :删除内容和定义,释放空间 + +## B+树索引和哈希索引的区别 + +B+树是一个平衡的多叉树,从根节点到每个叶子节点的高度差值不超过1,而且同层级的节点间有指针相互链接,是有序的 + +![](https://mmbiz.qpic.cn/mmbiz_jpg/UtWdDgynLdYnMu5lfXNAYzW0PPSOB8Pss8E5IlpSXicQbuCj5p3fN1vGtKkdUgeZ4IvYBx4IlFMLI4peDFvTV2w/640?wx_fmt=jpeg&tp=webp&wxfrom=5&wx_lazy=1) + +哈希索引就是采用一定的哈希算法,把键值换算成新的哈希值,检索时不需要类似B+树那样从根节点到叶子节点逐级查找,只需一次哈希算法即可,是无序的 + +![](https://mmbiz.qpic.cn/mmbiz_jpg/UtWdDgynLdYnMu5lfXNAYzW0PPSOB8PsAdicCricepbjicRIBIOlKdDPWlHroEiaYVgdDgicMMWbsuIlmmA4kOEVVog/640?wx_fmt=jpeg&tp=webp&wxfrom=5&wx_lazy=1) + +**优势对比:** diff --git a/interview/java/base.md b/interview/java/base.md index 7df15342..246a9eec 100644 --- a/interview/java/base.md +++ b/interview/java/base.md @@ -1,11 +1,16 @@ -- [HashMap ConcurrentHashMap](#hashmap-concurrenthashmap) +- [HashMap ConcurrentHashMap Hashtable](#hashmap-concurrenthashmap-hashtable) + - [为什么HashMap线程不安全](#为什么hashmap线程不安全) + - [如何线程安全的使用hashmap](#如何线程安全的使用hashmap) + - [TreeMap、HashMap、LindedHashMap的区别](#treemaphashmaplindedhashmap的区别) +- [try?catch?finally,try里有return,finally还执行么](#trycatchfinallytry里有returnfinally还执行么) - [java this 和 super的用法](#java-this-和-super的用法) - [this](#this) - [super](#super) - [super和this的异同:](#super和this的异同) - [抽象类和接口](#抽象类和接口) +- [java 重写和重载的区别](#java-重写和重载的区别) - [Synchronized 和 volitate区别](#synchronized-和-volitate区别) - [异常](#异常) - [String StringBuffer StringBuilder的区别](#string-stringbuffer-stringbuilder的区别) @@ -29,7 +34,7 @@ -# HashMap ConcurrentHashMap +# HashMap ConcurrentHashMap Hashtable HashMap和ConcurrentHashMap的最主要的区别就是前者是线程不安全,后者是线程安全的。在不同的JDK版本中,区别也不一样 @@ -45,6 +50,92 @@ ConcurrentHashMap 不用segment,改成CAS+synchronized方法实现。 CAS 的含义是“我认为原有的值应该是什么,如果是,则将原有的值更新为新值,否则不做修改,并告诉我原来的值是多少” +Hashtable 继承自陈旧的Directory,使用synchronized 同步,但是**不允许key和value为空** + +Hashtable使用Enumeration,HashMap使用Iterator + +HashMap 的迭代器:遍历的时候,根据Node数组的索引自然顺序,forEach +Hashtable 除了Iterator,自己实现了迭代器Enumeration,但是是从Node的**尾部到头部**开始遍历,不一样 + +hashtable elements() 方法获取的迭代器的下一个元素 + +``` java +@SuppressWarnings("unchecked") + public T nextElement() { + Entry et = entry; + int i = index; // index 为元素的长度 + Entry[] t = table; + /* Use locals for faster loop iteration */ + while (et == null && i > 0) { + et = t[--i]; + } + entry = et; + index = i; + if (et != null) { + Entry e = lastReturned = entry; + entry = e.next; + return type == KEYS ? (T)e.key : (type == VALUES ? (T)e.value : (T)e); + } + throw new NoSuchElementException("Hashtable Enumerator"); + } + +``` + +HashTable虽然性能上不如ConcurrentHashMap,但并不能完全被取代,两者的迭代器的一致性不同的,HashTable的迭代器是强一致性的,而ConcurrentHashMap是弱一致的。 + +ConcurrentHashMap的get,clear,iterator 都是弱一致性的。 Doug Lea 也将这个判断留给用户自己决定是否使用ConcurrentHashMap。 + +弱一致性的意思就是,put一个元素进去之后,不是马上对该元素可见。 + +## 为什么HashMap线程不安全 + +HashMap 在并发执行 put 操作时会引起死循环,导致 CPU 利用率接近100%。因为多线程会导致 HashMap 的 Node 链表形成环形数据结构,一旦形成环形数据结构,Node 的 next 节点永远不为空,就会在获取 Node 时产生死循环。 + +## 如何线程安全的使用hashmap + +三种方法: + +``` java +Map hashtable = new Hashtable<>(); +//synchronizedMap +Map synchronizedHashMap = Collections.synchronizedMap(new HashMap()); +//ConcurrentHashMap +Map concurrentHashMap = new ConcurrentHashMap<>(); +``` + +## TreeMap、HashMap、LindedHashMap的区别 + +LinkedHashMap可以保证HashMap集合有序,存入的顺序和取出的顺序一致。LinekdHashMap的Entry继承自HashMap.Node, 提供了双向指针。 + +LinkedHashMap 继承了HashMap,hashmap预留了三个函数,便于linkedHashMap对元素进行后续操作,下面三个函数在LinkedHashMap都有实现。 + +``` java + // Callbacks to allow LinkedHashMap post-actions + void afterNodeAccess(Node p) { } + void afterNodeInsertion(boolean evict) { } + void afterNodeRemoval(Node p) { } +``` + +TreeMap实现SortMap接口,能够把它保存的记录根据键排序,默认是按键值的升序排序,也可以指定排序的比较器,当用Iterator遍历TreeMap时,得到的记录是排过序的。 + +HashMap不保证顺序,即为无序的,具有很快的访问速度。 +HashMap最多只允许一条记录的键为Null;允许多条记录的值为 Null。 + +HashMap不支持线程的同步。 +我们在开发的过程中使用HashMap比较多,在Map中在Map 中插入、删除和定位元素,HashMap 是最好的选择。 + +但如果您要按自然顺序或自定义顺序遍历键,那么TreeMap会更好。 + +如果需要输出的顺序和输入的相同,那么用LinkedHashMap 可以实现,它还可以按读取顺序来排列。 + +总结:其实联系到三种hashmap的底层实现原理,很容易想到,TreeMap 的底层使用的是二叉堆来实现的,自然能够保证自动排序,HashMap底层使用数组实现,使用迭代器遍历的话,是根据key的hash值在存储表的索引来确定的,是无序的。LinkedHashMap底层使用的链表来存储数据,可根据插入的顺序来读取数据。 + +# try?catch?finally,try里有return,finally还执行么 + +肯定会执行。finally{}块的代码。 只有在try{}块中包含遇到System.exit(0)。 之类的导致Java虚拟机直接退出的语句才会不执行。 + +当程序执行try{}遇到return时,程序会先执行return语句,但并不会立即返回——也就是把return语句要做的一切事情都准备好,也就是在将要返回、但并未返回的时候,程序把执行流程转去执行finally块,当finally块执行完成后就直接返回刚才return语句已经准备好的结果。 + # java this 和 super的用法 ## this @@ -159,10 +250,6 @@ this和super不能同时出现在一个构造函数里面,因为this必然会 this()和super()都指的是对象,所以,均不可以在static环境中使用。包括:static变量,static方法,static语句块。 从本质上讲,this是一个指向本对象的指针, 然而super是一个Java关键字。 - - - - # 抽象类和接口 抽象类与接口: @@ -198,6 +285,10 @@ this()和super()都指的是对象,所以,均不可以在static环境中使 需要让不相关的类都实现一个方法,例如不相关的类都可以实现 Compareable 接口中的 compareTo() 方法; 需要使用多重继承,例如Runnable接口实现线程类 +# java 重写和重载的区别 + + + # Synchronized 和 volitate区别 [volatile与synchronized的区别](https://www.cnblogs.com/tf-Y/p/5266710.html) diff --git a/interview/network/http.md b/interview/network/http.md new file mode 100644 index 00000000..fede4e35 --- /dev/null +++ b/interview/network/http.md @@ -0,0 +1,32 @@ + + +- [Http常见状态码](#http常见状态码) + + +# Http常见状态码 + +2XX 成功 + +200 OK,表示从客户端发来的请求在服务器端被正确处理 +204 No content,表示请求成功,但响应报文不含实体的主体部分 +206 Partial Content,进行范围请求 + +3XX 重定向 + +301 moved permanently,永久性重定向,表示资源已被分配了新的 URL +302 found,临时性重定向,表示资源临时被分配了新的 URL +303 see other,表示资源存在着另一个 URL,应使用 GET 方法丁香获取资源 +304 not modified,表示服务器允许访问资源,但因发生请求未满足条件的情况 +307 temporary redirect,临时重定向,和302含义相同 + +4XX 客户端错误 + +400 bad request,请求报文存在语法错误 +401 unauthorized,表示发送的请求需要有通过 HTTP 认证的认证信息 +403 forbidden,表示对请求资源的访问被服务器拒绝 +404 not found,表示在服务器上没有找到请求的资源 + +5XX 服务器错误 + +500 internal sever error,表示服务器端在执行请求时发生了错误 +503 service unavailable,表明服务器暂时处于超负载或正在停机维护,无法处理请求 diff --git a/interview/note.md b/interview/note.md index 00d79642..b4bfea98 100644 --- a/interview/note.md +++ b/interview/note.md @@ -63,6 +63,8 @@ Java后端开发(大数据、分布式应用等) > [计算机网络基础](network/base.md) +> [Http](network/http.md) + ## 项目技能 > [分布式问题分析](../notes/分布式问题分析.md) diff --git a/interview/question.md b/interview/question.md index aa12e53f..fe5281bc 100644 --- a/interview/question.md +++ b/interview/question.md @@ -10,6 +10,8 @@ - [运输层](#运输层) - [算法和数结构](#算法和数结构) - [HTTP](#http) +- [设计模式](#设计模式) +- [分布式](#分布式) - [数据库](#数据库) - [Linux](#linux) - [安全](#安全) @@ -40,6 +42,13 @@ - @transactional注解在什么情况下会失效,为什么。 - java 基本类型的自动拆装箱的过程 - 内部类与静态内部类的区别 +- foreach与正常for循环效率对比 +- java 8 的新特性 +- AOP和OOP的区别 +- java 枚举 +- Java的四种引用,强弱软虚,用到的场景 +- foreach与正常for循环效率对比 +- java反射的作用于原理 ## IO @@ -82,7 +91,8 @@ - 悲观锁,乐观锁,优缺点,CAS有什么缺陷,该如何解决。 - 可重入锁的用处及实现原理,写时复制的过程,读写锁,分段锁(ConcurrentHashMap中的segment)。 - ABC三个线程如何保证顺序执行。 -- 线程状态 +- 线程状态以及状态之间的切换 +- ThreadLocal的了解,实现原理 # 操作系统 @@ -99,6 +109,7 @@ - TCP 洪泛攻击 - OSI 五层网络协议 - TCP和UDP的区别 +- 长连接和短连接。 连接池适合长连接还是短连接。 # 算法和数结构 @@ -108,17 +119,31 @@ - Hash算法和二叉树算法分别什么时候用 - 图的广度优先算法和深度优先算法:详见jvm中垃圾回收实现 - B-树和B+树的原理和应用场景 -- 十大排序算法的原理和复杂度,最好能够手撕出来。 +- 十大排序算法的原理和复杂度,最好能够手撕出来。(尤其是快排序和堆排序) ## HTTP - cookie和session的区别,分布式环境怎么保存用户状态; +# 设计模式 + +- 观察者模式 代理模式 单例模式 + +# 分布式 + +- 分布式事务 +- 分布式锁的设计 +- 分布式session # 数据库 - mysql 的索引分类 +- truncate与 delete区别 +- B+树索引和哈希索引的区别 +- 数据库事务 +- 四大基本特性?什么是隔离性?数据库并发有几个隔离级别? +- MySQL默认级别? # Linux diff --git a/interview/struct/datastruct.md b/interview/struct/datastruct.md index e69de29b..1d9a0a8e 100644 --- a/interview/struct/datastruct.md +++ b/interview/struct/datastruct.md @@ -0,0 +1,83 @@ + + +- [树](#树) + - [二叉树](#二叉树) + - [二叉树定义](#二叉树定义) + - [二叉树性质](#二叉树性质) + - [满二叉树](#满二叉树) + - [完全二叉树](#完全二叉树) + - [二叉查找树](#二叉查找树) + - [AVL树](#avl树) +- [参考链接](#参考链接) + + + +# 树 + +1. 树的定义 + +树是一种数据结构,它是由n(n>=1)个有限节点组成一个具有层次关系的集合。 + +2. 基本术语 + +若一个结点有子树,那么该结点称为子树根的"双亲",子树的根是该结点的"孩子"。有相同双亲的结点互为"兄弟"。一个结点的所有子树上的任何结点都是该结点的后裔。从根结点到某个结点的路径上的所有结点都是该结点的祖先。 + +结点的度:结点拥有的子树的数目。 +叶子:度为零的结点。 +分支结点:度不为零的结点。 +树的度:树中结点的最大的度。 + +层次:根结点的层次为1,其余结点的层次等于该结点的双亲结点的层次加1。 +树的高度:树中结点的最大层次。 +无序树:如果树中结点的各子树之间的次序是不重要的,可以交换位置。 +有序树:如果树中结点的各子树之间的次序是重要的, 不可以交换位置。 +森林:0个或多个不相交的树组成。对森林加上一个根,森林即成为树;删去根,树即成为森林。 + +## 二叉树 + +### 二叉树定义 + +二叉树是每个节点最多有两个子树的树结构。它有五种基本形态:二叉树可以是空集;根可以有空的左子树或右子树;或者左、右子树皆为空。 + +![](https://images0.cnblogs.com/i/497634/201403/270929530778327.jpg) + +### 二叉树性质 + +性质1:二叉树第i层上的结点数目最多为 2^(k-1) (i≥1)。 +性质2:深度为k的二叉树至多有2^k - 1个结点(k≥1)。 +性质3:包含n个结点的二叉树的高度至少为log2 (n+1)。 +性质4:在任意一棵二叉树中,若终端结点的个数为n0,度为2的结点数为n2,则n0=n2+1。 + +### 满二叉树 + +定义:高度为h,并且由2{h} –1个结点的二叉树,被称为满二叉树。 + +![](https://images0.cnblogs.com/i/497634/201403/270930282184259.jpg) + +### 完全二叉树 + +定义:一棵二叉树中,只有最下面两层结点的度可以小于2,并且最下一层的叶结点集中在靠左的若干位置上。这样的二叉树称为完全二叉树。 +特点:叶子结点只能出现在最下层和次下层,且最下层的叶子结点集中在树的左部。显然,一棵满二叉树必定是一棵完全二叉树,而完全二叉树未必是满二叉树。 + +![](https://images0.cnblogs.com/i/497634/201403/270931211084932.jpg) + +### 二叉查找树 + +定义:二叉查找树(Binary Search Tree),又被称为**二叉搜索树**。设x为二叉查找树中的一个结点,x节点包含关键字key,节点x的key值记为key[x]。如果y是x的左子树中的一个结点,则key[y] <= key[x];如果y是x的右子树的一个结点,则key[y] >= key[x]。 + +![](https://images0.cnblogs.com/i/497634/201403/270932052801072.jpg) + +在二叉查找树中: +(01) 若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值; +(02) 任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值; +(03) 任意节点的左、右子树也分别为二叉查找树。 +(04) **没有键值相等的节点(no duplicate nodes)。** + +## AVL树 + +定义:自平衡二叉查找树 + +# 参考链接 + +- [数据结构](https://blog.csdn.net/qq_31196849/article/details/78529724) +- [数据结构全](https://blog.csdn.net/heyuchang666/article/details/49891635) \ No newline at end of file