去哪儿网面经

链接:https://www.nowcoder.com/discuss/113837
 

一面:

从来没有那么流利的回答过面试官的问题!大部分都是面试官一说,我马上答出来,以至于我稍微有点停顿的时候,面试官马上说:你别急,先想想!(其实我只是说累!)

问题比较多!记不太清了!

 

1、HashMap 内部结构、put操作流程

https://blog.csdn.net/strawqqhat/article/details/88667705

2、手写反转链表

https://blog.csdn.net/strawqqhat/article/details/88668713

3、手写快排(由于我贝壳面试的时候,面试官说我代码写得慢!然后这次我写得贼快!面试官厕所都没上完我就写完了……,然后面试官说你写得这么快啊!我内心一顿窃喜!)

https://blog.csdn.net/strawqqhat/article/details/88669225

4、ThreadLocal

ThreadLocal用于保存某个线程共享变量:对于同一个static ThreadLocal,不同线程只能从中get,set,remove自己的变量,而不会影响其他线程的变量。

1、ThreadLocal.get: 获取ThreadLocal中当前线程共享变量的值。

2、ThreadLocal.set: 设置ThreadLocal中当前线程共享变量的值。

3、ThreadLocal.remove: 移除ThreadLocal中当前线程共享变量的值。

4、ThreadLocal.initialValue: ThreadLocal没有被当前线程赋值时或当前线程刚调用remove方法后调用get方法,返回此方法值。

5、线程池

https://blog.csdn.net/strawqqhat/article/details/88670869

6、垃圾回收器

https://blog.csdn.net/strawqqhat/article/details/86434313#GC%E6%9C%BA%E5%88%B6%E8%AE%B2%E4%B8%80%E8%AE%B2

7、redis特点、应用场景等……

https://blog.csdn.net/strawqqhat/article/details/88671013

8、缓存一致性问题(这题我特地温习了一遍!,但是当时一时短路,回答的不是很好,面试官给我解释了一下)

https://blog.csdn.net/strawqqhat/article/details/88673373

9、Linux关于查找日志的命令!(这题只要求我说出能想出什么命令,我好久没碰Linux了,怎么可能记得!只大概说了几个)

1.查看日志常用命令

    tail:  

       -n  是显示行号;相当于nl命令;例子如下:

            tail -100f test.log      实时监控100行日志

            tail  -n  10  test.log   查询日志尾部最后10行的日志;

            tail -n +10 test.log    查询10行之后的所有日志;

    head:  

        跟tail是相反的,tail是看后多少行日志;例子如下:

            head -n 10  test.log   查询日志文件中的头10行日志;

            head -n -10  test.log   查询日志文件除了最后10行的其他所有日志;

    cat: 

        tac是倒序查看,是cat单词反写;例子如下:

            cat -n test.log |grep "debug"   查询关键字的日志

 

2. 应用场景一:按行号查看---过滤出关键字附近的日志

     1)cat -n test.log |grep "debug"  得到关键日志的行号

     2)cat -n test.log |tail -n +92|head -n 20  选择关键字所在的中间一行. 然后查看这个关键字前10行和后10行的日志:

            tail -n +92表示查询92行之后的日志

            head -n 20 则表示在前面的查询结果里再查前20条记录

 

3. 应用场景二:根据日期查询日志

      sed -n '/2014-12-17 16:17:20/,/2014-12-17 16:17:36/p'  test.log

      特别说明:上面的两个日期必须是日志中打印出来的日志,否则无效;

                      先 grep '2014-12-17 16:17:20' test.log 来确定日志中是否有该 时间点

 

4.应用场景三:日志内容特别多,打印在屏幕上不方便查看

    (1)使用more和less命令,

           如: cat -n test.log |grep "debug" |more     这样就分页打印了,通过点击空格键翻页

    (2)使用 >xxx.txt 将其保存到文件中,到时可以拉下这个文件分析

            如:cat -n test.log |grep "debug"  >debug.txt

10、应用题(我感觉能问到这题一面基本都过了吧,我项目经验比较少,面试官没有为难我)

面试官很友善!!!

 

二面:

难度又上升了一个档次!有些题目磕磕绊绊的说出来了,可能是因为一面面试官对我的评价高(特指Java基础!!!)。

二面面试官之后也只是“对我项目经验的的评价不是很高”(出自HR之口,意思就是你项目经验真的垃圾!!!)

二面面试官给我一种大佬即视感的感觉!!因为我回答问题,我感觉回答完了!他总会说一句还有呢……我心里就在想,还有什么???

 

1、HTTP、HTTPS(如何保证安全)

1.理解http与https的概念

(1)HTTP:超文本传输协议 (HTTP-Hypertext transfer protocol),是互联网上应用最为广泛的一种网络协议,是一种详细规定了浏览器和万维网服务器之间互相通信的规则,通过因特网传送万维网文档的数据传送协议。用于从WWW服务器传输超文本到本地浏览器的传输协议,它可以使浏览器更加高效,使网络传输减少。

     HTTP的会出现的问题:http协议属于明文传输协议,交互过程以及数据传输都没有进行加密,通信双方也没有进行任何认证,通信过程非常容易遭遇劫持、监听、篡改,严重情况下,会造成恶意的流量劫持等问题,甚至造成个人隐私泄露(比如银行卡卡号和密码泄露)等严重的安全问题。

(2)HTTPS是以安全为目标的HTTP通道,简单讲是HTTP的安全版,即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。现在它被广泛用于万维网上安全敏感的通讯,例如交易支付方面。

    HTTPS协议可以分为两种:一是通过建立一个信息安全通道,来保证数据传输的安全;二是通过确认网站的真实性。

HTTPS在HTTP的基础上加入了SSL/TLS协议,依靠SSL证书来验证服务器的身份,并为客户端和服务器端之间建立“SSL加密通道”,确保用户数据在传输过程中处于加密状态,同时防止服务器被钓鱼网站假冒,而HTTP协议无法加密数据,所有通信数据都在网络中明文“裸奔”。通过网络的一些技术手段,就可还原HTTP报文内容。

https与http的对比图

 

2.简要了解HTTP和HTTPS的区别?

(1)HTTP 是超文本传输协议,属于明文传输协议,HTTPS 则是具有安全性的基于ssl加密的传输协议

(2)HTTP 和 HTTPS 使用的是连接方式不同,而且用的端口也不一样,前者是80,后者是443。

(3)HTTP 是简单的无状态的连接。HTTPS 协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议 要比 HTTP 协议安全

(4)HTTPS 内容经过对称加密,每个连接生成一个唯一的加密密钥(对称秘钥:对称密钥加密又叫专用密钥加密,即发送和接收数据的双方必使用相同的密钥对明文进行加密和解密运算。)

(5)HTTPS 内容传输经过完整性校验

3.HTTPS是如何保证数据的安全?

(1)客户端向服务器端发起SSL连接请求;(在此过程中依然存在数据被中间方盗取的可能,下面将会说明如何保证此过程的安全)

(2) 服务器把公钥发送给客户端,并且服务器端保存着唯一的私钥

(3)客户端用公钥对双方通信的对称秘钥进行加密,并发送给服务器端

(4)服务器利用自己唯一的私钥对客户端发来的对称秘钥进行解密,在此过程中,中间方无法对其解密(即使是客户端也无法解密,因为只有服务器端拥有唯一的私钥),这样保证了对称秘钥在收发过程中的安全,此时,服务器端和客户端拥有了一套完全相同的对称秘钥。

(5)进行数据传输,服务器和客户端双方用公有的相同的对称秘钥对数据进行加密解密,可以保证在数据收发过程中的安全,即是第三方获得数据包,也无法对其进行加密,解密和篡改。

 

2、HTTP请求和响应报文段(这块不是很熟,说了一些出来)

https://www.jianshu.com/p/0015277c6575

3、手写请求头,响应头!!!

https://www.cnblogs.com/konglingxi/p/9558501.html

4、优先队列数据结构

优先队列原理与实现

  优先队列是一种用来维护一组元素构成的结合S的数据结构,其中每个元素都有一个关键字key,元素之间的比较都是通过key来比较的。优先队列包括最大优先队列和最小优先队列,优先队列的应用比较广泛,比如作业系统中的调度程序,当一个作业完成后,需要在所有等待调度的作业中选择一个优先级最高的作业来执行,并且也可以添加一个新的作业到作业的优先队列中。Java中,PriorityQueue的底层数据结构就是堆(默认是小堆),关于Java的PriorityQueue更多知识请点击:深入理解Java PriorityQueue

  优先队列的实现中,我们可以选择堆数据结构,最大优先队列可以选用大堆,最小优先队列可以选用小堆来实现。下面以最大优先队列来讲解其原理。最大优先队列一般包括将一个元素插入到集合S中、返回集合S中具有最大key的元素、返回并删除集合S中具有最大key的元素等。

插入操作

  插入操作是将一个元素插入到集合S中,首先把该元素放入所有元素的下一位置,然后执行“上浮”操作,如下图示例(注意,下图示例是小堆,不过原理是一样的,图片来自深入理解Java PriorityQueue)

)PriorityQueue_offer.png

移除操作

  优先队列中,在队列非空情况下移除集合中第一个元素,也就是下标为0的元素,然后将集合中最后一个元素移到下标为0位置,在将下标为0的新元素执行“下沉”操作。如下图示例(注意,下图示例是小堆,不过原理是一样的,图片来自深入理解Java PriorityQueue)

PriorityQueue_poll.png

完整代码实现

复制代码

package priorityheap;

import java.util.Arrays;

/**
 * 优先队列类(最大优先队列)
 */
public class PriorityHeap {

    // ------------------------------ Instance Variables

    private int[] arr;
    private int size;

    // ------------------------------ Constructors

    /**
     * 优先队列数组默认大小为64
     */
    public PriorityHeap() {
        this(64);
    }

    public PriorityHeap(int initSize) {
        if (initSize <= 0) {
            initSize = 64;
        }
        this.arr = new int[initSize];
        this.size = 0;
    }

    // ------------------------------ Public methods

    public int max() {
        return this.arr[0];
    }

    public int maxAndRemove() {
        int t = max();

        this.arr[0] = this.arr[--size];
        sink(0, this.arr[0]);
        return t;
    }
    public void add(int data) {
        resize(1);
        this.arr[size++] = data;
        pop(size - 1, data);
    }

    // ------------------------------ Private methods

    /**
     * key下沉方法
     */
    private void sink(int i, int key) {
        while (2 * i <= this.size - 1) {
            int child = 2 * i;
            if (child < this.size - 1 && this.arr[child] < this.arr[child + 1]) {
                child++;
            }
            if (this.arr[i] >= this.arr[child]) {
                break;
            }

            swap(i, child);
            i = child;
        }
    }

    /**
     * key上浮方法
     */
    private void pop(int i, int key) {
        while (i > 0) {
            int parent = i / 2;
            if (this.arr[i] <= this.arr[parent]) {
                break;
            }
            swap(i, parent);
            i = parent;
        }
    }

    /**
     * 重新调整数组大小
     */
    private void resize(int increaseSize) {
        if ((this.size + increaseSize) > this.arr.length) {
            int newSize = (this.size + increaseSize) > 2 * this.arr.length ? (this.size + increaseSize) : 2 * this.arr.length;
            int[] t = this.arr;

            this.arr = Arrays.copyOf(t, newSize);
        }
    }

    /**
     * Swaps arr[a] with arr[b].
     */
    private void swap(int a, int b) {
        int t = this.arr[a];
        this.arr[a] = this.arr[b];
        this.arr[b] = t;
    }
}

 

5、红黑树和AVL树的区别(这题我把红黑树的性质特点说出来了,但是没答到点上,这题算是回答的最差的一题了)

https://blog.csdn.net/strawqqhat/article/details/88679849

6、说一下笔试题的思路

7、数据库索引!!!

关于数据库索引,相信大家用到最多的一定是数据库设计和数据库查询,本篇深度解析一下数据库索引的原理,涉及数据库本身的设计原理,对设计应用的数据库结构,和数据库查询也大有益处。

 

(一)在了解数据库索引之前,首先了解一下数据库索引的数据结构基础,B+tree

B+tree 是一个n叉树,每个节点有多个叶子节点,一颗B+树包含根节点,内部节点,叶子节点。根节点可能是一个叶子节点,也可能是一个包含两个或两个以上叶子节点的节点。

B+tree的性质:

1.n棵子tree的节点包含n个关键字,不用来保存数据而是保存数据的索引。

2.所有的叶子结点中包含了全部关键字的信息,及指向含这些关键字记录的指针,且叶子结点本身依关键字的大小自小而大顺序链接。

3.所有的非终端结点可以看成是索引部分,结点中仅含其子树中的最大(或最小)关键字。

B+tree结构原型图大概如下(引用):

这里还有一篇百度文库文章可以参考 http://wenku.baidu.com/link?url=qniQ1rpN8XOlbs4Vu6pjd_7YzVOGYxmBH0TeHLJTvwQ3Qs9Ig-FJyodXSaeBc3Ap7nC6Rm9qD6We5oJL-j7vnM4Ro5Y5J7yHwCk3asL_q5e

由于B+tree的性质, 它通常被用于数据库和操作系统的文件系统中。NTFS, ReiserFS, NSS, XFS, JFS, ReFS 和BFS等文件系统都在使用B+树作为元数据索引,因为B+ 树的特点是能够保持数据稳定有序,其插入与修改拥有较稳定的对数时间复杂度(B+ 树元素自底向上插入)。

(二)数据库索引

数据库索引是用于提高数据库表的数据访问速度的。

数据库索引的特点:

a)避免进行数据库全表的扫描,大多数情况,只需要扫描较少的索引页和数据页,而不是查询所有数据页。而且对于非聚集索引,有时不需要访问数据页即可得到数据。

b)聚集索引可以避免数据插入操作,集中于表的最后一个数据页面。

c)在某些情况下,索引可以避免排序操作。

数据库索引的存储方式,类型,在运行时的操作原理,我制作成了下图:

 

8、线程池实现原理

https://blog.csdn.net/strawqqhat/article/details/88680342

9、应用题,关于建索引(这题考察的是什么来着,我忘记了!以前看面经的时候提到的一个算法)

 

还有很多题目,记不清了……因为真的问得太多了……

 

HR面:

我就说一点,与顺丰HR相比,我感觉去哪儿网HR的每一次点头都是对我的认可,顺丰HR可能是习惯性点头……

HR还跟我说了,关于我表述时口头禅的问题……这点特别不好,大家要注意!

posted @ 2019-03-19 21:24  strawqqhat  阅读(305)  评论(0编辑  收藏  举报
#home h1{ font-size:45px; } body{ background-image: url("放你的背景图链接"); background-position: initial; background-size: cover; background-repeat: no-repeat; background-attachment: fixed; background-origin: initial; background-clip: initial; height:100%; width:100%; } #home{ opacity:0.7; } .wall{ position: fixed; top: 0; left: 0; bottom: 0; right: 0; } div#midground{ background: url("https://i.postimg.cc/PP5GtGtM/midground.png"); z-index: -1; -webkit-animation: cc 200s linear infinite; -moz-animation: cc 200s linear infinite; -o-animation: cc 200s linear infinite; animation: cc 200s linear infinite; } div#foreground{ background: url("https://i.postimg.cc/z3jZZD1B/foreground.png"); z-index: -2; -webkit-animation: cc 253s linear infinite; -o-animation: cc 253s linear infinite; -moz-animation: cc 253s linear infinite; animation: cc 253s linear infinite; } div#top{ background: url("https://i.postimg.cc/PP5GtGtM/midground.png"); z-index: -4; -webkit-animation: da 200s linear infinite; -o-animation: da 200s linear infinite; animation: da 200s linear infinite; } @-webkit-keyframes cc { from{ background-position: 0 0; transform: translateY(10px); } to{ background-position: 600% 0; } } @-o-keyframes cc { from{ background-position: 0 0; transform: translateY(10px); } to{ background-position: 600% 0; } } @-moz-keyframes cc { from{ background-position: 0 0; transform: translateY(10px); } to{ background-position: 600% 0; } } @keyframes cc { 0%{ background-position: 0 0; } 100%{ background-position: 600% 0; } } @keyframes da { 0%{ background-position: 0 0; } 100%{ background-position: 0 600%; } } @-webkit-keyframes da { 0%{ background-position: 0 0; } 100%{ background-position: 0 600%; } } @-moz-keyframes da { 0%{ background-position: 0 0; } 100%{ background-position: 0 600%; } } @-ms-keyframes da { 0%{ background-position: 0 0; } 100%{ background-position: 0 600%; } }