百度一面的面经(简答题自己添加了答案,以及相关知识)

2020-07-19  本文已影响0人  coder_girl

第一次直接做机试:

题目:

image

实现一个点赞功能,要求:

任何一个用户可以发布一串字符串内容.

所有用户都可以看发布的内容,并进行点赞,盖内若能的点赞数需要累加统计

任何一个用户,取消点赞的内容,可以进行取消点赞,该内容的点赞数需要扣减

自行设计数据库以及项目框架搭建并且实现功能

点赞功能:小demo连接

过了一天晚上又打了个电话面试主要的问题我如下列出来:

1.自我介绍,项目介绍

2. sql索引以及原理

index

索引原理:B+树

优化:

主要是在所有的叶子结点中增加了指向下一个叶子节点的指针,因此InnoDB建议为大部分表使用自增的主键作为索引.

无法使用索引的场景(自己觉得比较重要的)

1.以"%"开头的LIKE语句,模糊查询

2.OR语句前后没有同事使用索引

3.数据类型出现隐式转化(如varchar不加单引号的话可能自动转换为int型)

索引:是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),他们包含着对数据有记录的引用指针.

联合索引(面试常客)

最左匹配原则,筛选数据最多的字段放在左侧.

(A,B,C) 这样3列,mysql会首先匹配A,abc ac ab ac 或者cba cab ca ba

就是一定要有最左边的元素才会使用到索引

3. 介绍一下springboot

SpringBoot是一个快速开发的框架应用,封装了Maven常用依赖,能够快速地整合第三方框架;简化xml配置,全部采用注解形式,内置Tomcat,Jetty,Undertow,帮助开发者能够实现快速开发,SpringBoot的web组件,默认集成的是SpringMvc框架.

springboot原理:

4.常用git命令有哪些

5.常用的集合类有哪些,然后延伸问hash map的原理以及hashtable的原理和concurrent haspmap的原理

集合类:

image.png

常用的集合类:

一, Collection接口

(1). collection接口的成员方法

增加: boolean add(E e)

删除: boolean remove(Object o)

清空: void clear()

包含: boolean contains(Object o)

判断为空: boolean isEmpty()

容量: int size()

boolean addAll(Collection c)

boolean removeAll(Collection c)

boolean containsAll(Collection c)

boolean retainAll(Collection c)

(2). Object[] toArray()

把集合转成数组,可以实现集合的遍历.

(3). Iterator iterator()

迭代器,集合的专用遍历方式.

使用方法iterator()要求容器返回一个Iterator

boolean hasNext() 检查是否有下一个元素

E next() 获取下一个元素

remove() 将迭代器新进返回的元素删除

1, List接口(继承Connection)

ArrayList(开发中用的很多)

底层数据结构是一个自增长的数组,查询快,增删慢.

线程不安全,效率高.

LinkedList

底层数据结构是链表(存储地址不连续),查询慢,增删快

线程不安全,效率高

LinkedList类特有功能

public void addFirst(E e)及addLast(E e)

public E getFirst()及getLast()

public E removeFirst()及public E removeLast()

Vector

底层数据结构是也是数组,查询快,增删慢.

线程安全,效率低.

Vector类特有功能:

public void addElement(E obj)

public E elementAt(int index)

public Enumeration elements()

2, Set接口(继承Connection)

Set是一个不包含重复元素的 collection。Set中最常被使用的是测试归属性,你可以很容易的查询某个对象是否在其中。正因如此,查找成了set中的重要操作,因此你通常都会选择一个HashSet实现,它专门进行了优化。

Set具有与Collection完全一样的接口,因此没有任何额外的功能,不像List一样有不同的list。实际上Set就是Collection,只是行为不同。加入Set的元素必须定义equals方法以确保对象的唯一性

HashSet:为快速查找而设计的Set。存入HashSet的元素必须定义hashCode()方法,不保证set的迭代顺序,特别是它不保证该顺序恒久不变。

HashSet如何保证元素唯一性?底层数据结构是哈希表(元素是链表的数组)哈希表依赖于哈希值存储添加功能底层依赖两个方法: int hashCode()

boolean equals(Object obj)

LinkedHashSet:具有HashSet的查询速度,且内部使用链表维护元素的顺序(插入的次序)。于是在使用迭代器遍历Set时,结果会按元素插入的次序显示。元素也必须定义hashCode()方法

元素有序唯一

由链表保证元素有序

由哈希表保证元素唯一

TreeSet:保持次序的set,底层为树结构。使用它可以从set中提取有序的序列。元素必须实现Comparable接口。

使用元素的自然顺序对元素进行排序

或者根据创建 set 时提供的 Comparator 进行排序

具体取决于使用的构造方法。

必须提的一点:TreeSet是如何保证元素的排序和唯一性的?

底层数据结构是红黑树(红黑树是一种自平衡的二叉树)!

各种set集合性能分析

HashSet和TreeSet是Set集合中用得最多的集合。HashSet总是比TreeSet集合性能好,因为HashSet不需要额外维护元素的顺序。

LinkedHashSet需要用额外的链表维护元素的插入顺序,因此在插入时性能比HashSet低,但在迭代访问(遍历)时性能更高。因为插入的时候即要计算hashCode又要维护链表,而遍历的时候只需要按链表来访问元素。

EnumSet元素是所有Set元素中性能最好的,但是它只能保存Enum类型的元素

3, Queue接口

Queue队列,它主要分为两大类,一类是阻塞式队列,队列满了以后再插入元素则会抛出异常,主要包括ArrayBlockQueue、PriorityBlockingQueue、LinkedBlockingQueue。另一类则是双端队列,支持在头、尾两端插入和移除元素,主要包括:ArrayDeque、LinkedBlockingDeque、

****LinkedList

Queue用于模拟队列这种数据结构,队列通常是指“先进先出”的容器。队列的头部保存在队列中时间最长的元素,队列的尾部 保存在队列中时间最短的元素。新元素插入到队列的尾部,访问元素操作会返回队列头部的元素。通常,队列不允许随机访问队列中的元素。

Queue接口中定义了如下操作方法:

void add(Object e): 将指定元素加入此队列的尾部。

Object element(): 获取队列头部的元素,但是不删除该元素。

boolean offer(Object e): 将指定元素加入此队列的尾部。当使用有容量限制的队列时,此方法通常比add(Object e)方法更好。

Object peek(): 获取队列头部的元素,但是不删除该元素。如果此队列为空,则返回null。

Object poll(): 获取队列头部的元素,并删除该元素。如果此队列为空,则返回null。

Object remove(): 获取队列头部的元素,并删除该元素。

Queue有两个常用的实现类:LinkedList和PriorityQueue。

LinkedList类 是一个比较奇怪的类,它是List接口的实现类–这意味着它是一个List集合,可以根据索引来随机访问集合中的元素。除此之外,LinkedList还实现了Deque接口,Deque接口是Queue接口的子接口,它代表一个双向队列Deque接口里定义了一些可以双向操作队列的方法。

LinkedList与ArrayList的实现机制完全不同,ArrayList内部以数组的形式来保存集合中的元素,因此随机访问集合元素上有较好的性能;而LinkedList内部以链表的形式来保存集合中的元素,因此随机访问集合元素时性能较差,但在插入、删除元素时性能非常出色(只需改变指针所指的地址即可)。

通常的编程过程中无须理会ArrayList和LinkedList之间的性能差异,只需知道LinkedList集合不仅提供了List的

功能,还额外提供了的双向队列、栈的功能。但在一些性能非常敏感的地方,可能需要慎重选择哪个List实现。

4, Map接口(实现Connection)

Map的思想,映射表(也可以称为关联数组)的基本思想是它维护的键-值(对)关联,因此你可以使用键来查找值。标准的Java类库中包含了Map的集中基本实现类,包括HashMap,TreeMap、LinkedHashMap、WeakHashMap,ConcurrentHashMap、IdentityHashMap。它们都有同样的基本接口Map,但是行为特效各不同,这表现在效率、键值对的保存及呈现次序、对象的保存周期、映射表如何在多线程程序中工作和判定“键”等价的策略等方面。Map接口实现的数量应该可以让你感觉到这种工具的重要性。

Map接口成员方法:

V put(K key,V value)

V remove(Object key)

void clear()

boolean containsKey(Object key)

boolean containsValue(Object value)

boolean isEmpty()

int size()

V get(Object key)

Set keySet()

Collection values()

Set<Map.Entry<K,V>> entrySet()

这里提一下Map的遍历方式吧:

方式1:根据键找值

获取所有键的集合

遍历键的集合,获取到每一个键

根据键找值

方式2:根据键值对对象找键和值

获取所有键值对对象的集合

遍历键值对对象的集合,获取到每一个键值对对象

根据键值对对象找键和值

HashMap:Map基于散列表的实现(它取代 了Hashtable)。插入和查询“键值对”的开销是固定的。可以通过构造器设置容器和负载因子,以调整容器的性能。

LinkedHashMap:类似于HashMap,但是迭代遍历它时,取得“键值对”的顺序是其插入次序,或者是最近最少使用的(LRU)的次序。只是比HashMap慢一点,而在迭代访问时,反而更快,因为它使用链表维护内部次序。

TreeMap:基于红黑树的实现,查看“键”或“键值对”时,它们会被排序(次序由Comparable或Comparator决定)。TreeMap的特点在于所得到的结果是经过排序的。TreeMap是唯一带有subMap()方法的Map,它可以返回一个子树

WeakHashMap:弱键(weak key)映射,允许释放映射所指向的对象,这是为解决某类特殊问题而设计的。如果映射之外没有引用指向某个“键”,则此键可以被垃圾回收器回收。

ConcurrentHashMap:一种线程安全的Map,它不涉及加同步锁。

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

既然谈到了HashMap那么就来总结一下与Hashtable的不同,最直观的方法,看其底层实现的源码。

1.它们的家族就不同,虽然都实现了Map接口,但HashMap是继承自AbstractMap,Hashtable继承自古老的Dictionary

2.HashMap是允许key为null的,而Hashtbale是不允许的

3.在Hashtable的源码里,一眼我们就能看到一个关键字 -----synchronized ,所以其是线程同步的,HashMap不是线程同步的,所以效率会高上一些,简而言之,HashMap是Hashtable的轻量级实现(非线程安全实现)

最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在多个线程访问Hashtable时,不需要自己为它的方法实现同步,而HashMap 就必须为之提供外同步(Collections.synchronizedMap)。

二、各种集合的异同点

1、Vector和ArrayList

1,vector是线程同步的,所以它也是线程安全的,而arraylist是线程异步的,是不安全的。如果不考虑到线程的安全因素,一般用arraylist效率比较高。

2,如果集合中的元素的数目大于目前集合数组的长度时,vector增长率为目前数组长度的100%,而arraylist增长率为目前数组长度的50%.如果在集合中使用数据量比较大的数据,用vector有一定的优势。

3,如果查找一个指定位置的数据,vector和arraylist使用的时间是相同的,都是0(1),这个时候使用vector和arraylist都可以。而如果移动一个指定位置的数据花费的时间为0(n-i)n为总长度,这个时候就应该考虑到使用arraylist,因为它移动一个指定位置的数据所花费的时间为0(1),而查询一个指定位置的数据时花费的时间为0(i)。

ArrayList 和Vector是采用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,都允许直接序号索引元素,但是插入数据要涉及到数组元素移动等内存操作,所以索引数据快插入数据慢,Vector由于使用了synchronized方法(线程安全)所以性能上比ArrayList要差,LinkedList使用双向链表实现存储,按序号索引数据需要进行向前或向后遍历,但是插入数据时只需要记录本项的前后项即可,所以插入数度较快!

2、Aarraylist和Linkedlist

1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。

2.对于随机访问get和set,ArrayList绝对优于LinkedList,因为LinkedList要移动指针。

3.对于新增和删除操作add和remove,LinkedList比较占优势,因为ArrayList要移动数据。

这一点要看实际情况的。若只对单条数据插入或删除,ArrayList的速度反而优于LinkedList。但若是批量随机的插入删除数据,LinkedList的速度大大优于ArrayList. 因为ArrayList每插入一条数据,要移动插入点及之后的所有数据。

3、HashMap与TreeMap

1、 HashMap通过hashcode对其内容进行快速查找,而TreeMap中所有的元素都保持着某种固定的顺序,如果你需要得到一个有序的结果你就应该使用TreeMap(HashMap中元素的排列顺序是不固定的)。集合框架”提供两种常规的Map实现:HashMap和TreeMap (TreeMap实现SortedMap接口)。

2、在Map 中插入、删除和定位元素,HashMap 是最好的选择。但如果您要按自然顺序或自定义顺序遍历键,那么TreeMap会更好。使用HashMap要求添加的键类明确定义了hashCode()和 equals()的实现。 TreeMap没有这个调优选项,因为该树总处于平衡状态。

4、hashtable与hashmap

1、历史原因:Hashtable是基于陈旧的Dictionary类的,HashMap是Java 1.2引进的Map接口的一个实现 。

2、同步性:Hashtable是线程安全的,也就是说是同步的,而HashMap是线程序不安全的,不是同步的 。

3、值:只有HashMap可以让你将空值作为一个表的条目的key或value 。

hashmap原理:数组+链表(1.8之后:链长超过8时将链表转换成红黑树前会判断,如果当前数组的长度小于 64,那么会选择先进行数组扩容,而不是转换为红黑树)时,将链表转化为红黑树,以减少搜索时间。Hashtable 没有这样的机制.

hashTable原理: 数组+链表,HashTable 是线程安全的,因为 HashTable 内部的方法基本都经过synchronized 修饰。

concurrenthashmap:jdk1.7:分组数组+链表(**** ① 在 JDK1.7 的时候,ConcurrentHashMap(分段锁) 对整个桶数组进行了分割分段(Segment),每一把锁只锁容器其中一部分数据,多线程访问容器里不同数据段的数据,就不会存在锁竞争,提高并发访问率。 到了 JDK1.8 的时候已经摒弃了 Segment 的概念,而是直接用 Node 数组+链表+红黑树的数据结构来实现,并发控制使用 synchronized 和 CAS 来操作。)

6. Linux命令

常用命令:

cd 进入目录

chmod 777 授权所有权限

./start.sh 运行

查看log(日志)的操作

cd ./XXXXX/log/catXXX.log

tail -f XXX.log 从下往上滚的查看

cat -n "日志名称" | grep "要查询的错误"

7. springboot的常用注解

springboot核心注解:

@SpringBootApplication= @SpringBootConfiguration+@EnableAutoConfiguration+@ComponentScan

:开启Springboot各项功能

**@EnableAutoConfiguration:允许自动配置注解 **

@SpringBootConfiguration

这个注解就是 @Configuration 注解的变体,只是用来修饰是 Spring Boot 配置而已,或者可利于 Spring Boot 后续的扩展。

@ComponentScan

这是 Spring 3.1 添加的一个注解,用来代替配置文件中的 component-scan 配置,开启组件扫描,即自动扫描包路径下的 @Component 注解进行注册 bean 实例到 context 中。

8.springboot打包的方式有哪些,区别是,如果只是把主类打包怎么加依赖

springboot打jar包有两种方式:

1.通过Maven插件,将所有依赖都打成一个jar包,然后通过java -jar XXX.jar方式运行

2.将主程序打成jar包,然后和其他依赖包放在一起(包括Maven下载的和第三方jar包),这样也可以通过java -jar xxx.jar方式运行

jar方式运行的前提是主程序jar包中的META-INF文件夹下的MANIFEST.MF文件必须有正确的Class-Path、Main-Class。

Class-Path指定了主程序依赖的jar包,若配置错误,运行jar时将报ClassNotFoundException;若新增或删除了一些jar包,需要删除该文件,并重新生成。

Main-Class指定了程序的运行入口,这里配置成SpringBoot的主函数。

MANIFEST.MF文件若配置不当,运行jar时将报xxxxxx.jar中没有主清单属性。

详情可点击搜看

........

上一篇下一篇

猜你喜欢

热点阅读