面試題隨記二


從7月2號開始,到7月21號結束,14個工作日,參加了15場面試。其中:

滴滴:面4場

美團:面3場

自如:面2場

小米:面3場

去哪兒:面1場

Boss直聘:面2場

工作3年,終於拿到了心儀的offer,在這里做一個記錄。

因平時上班事情比較多,再加上面試比較密集,所以沒能及時的對每一次面試做一個復盤,導致面試遇到的好多東西都已經忘了,所以這里就只能撿我在微信文件助手里面的幾個有意思的記錄來寫了。

好記性不如爛筆頭,寫出來一是給自己做一個筆記,二是也希望分享出來能對其他朋友有所幫助。


美團二面

1、如果因為一些原因,線上Redis掛了,然后所有請求打到數據庫層導致數據庫也掛了,這時該怎么進行恢復?

就以我三年的工作經驗來說顯然是超出了我的范圍,沒遇到過這樣的場景,平時也沒怎么想過,然后當時的第一思路就是先做限流,然后逐步恢復Redis和數據庫。

很明顯,當時這個問題我回答的並沒有讓面試官滿意,但是實在所見有限,沒有其他思路了,歡迎路過的朋友給一些其他思路。

2、Spring里面的bean id是否允許重復?如果允許重復的話重復了怎么辦?如果不允許重復是怎么處理的?

因為在我的個人簡歷里面寫了自己深入閱讀過Spring源碼的,所以這一個問題明顯是就這一項的發問,當時自己確實記得是不允許重復的,所以回答的是不允許重復,如果重復了拋出bean重復定義的異常。然后面試官當場給我指出來說是允許重復的,如果重復了的話后加載進來的是覆蓋前面的,不會做拋錯。

針對這個問題,我重新翻閱了一下Spring源碼,原來我記混淆了,會拋出異常的是beanDefinition,處理邏輯如下方法:

DefaultListableBeanFactory.registerBeanDefinition

	@Override
	public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException {
		// 刪掉了一部分代碼

		BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
		if (existingDefinition != null) {
			if (!isAllowBeanDefinitionOverriding()) {
				throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
			}
			else if (existingDefinition.getRole() < beanDefinition.getRole()) {
				if (logger.isInfoEnabled()) {
					logger.info("Overriding user-defined bean definition for bean '" + beanName +
							"' with a framework-generated bean definition: replacing [" +
							existingDefinition + "] with [" + beanDefinition + "]");
				}
			}
			else if (!beanDefinition.equals(existingDefinition)) {
				if (logger.isDebugEnabled()) {
					logger.debug("Overriding bean definition for bean '" + beanName +
							"' with a different definition: replacing [" + existingDefinition +
							"] with [" + beanDefinition + "]");
				}
			}
			else {
				if (logger.isTraceEnabled()) {
					logger.trace("Overriding bean definition for bean '" + beanName +
							"' with an equivalent definition: replacing [" + existingDefinition +
							"] with [" + beanDefinition + "]");
				}
			}
			this.beanDefinitionMap.put(beanName, beanDefinition);
		}
		else {
			// 刪掉了一部分代碼
		}

		// 刪掉了一部分代碼
	}

可以看出,beanDefinition重復是否會拋出異常也是結合配置來說的。而對於實例id重復,那么直接是覆蓋了,如代碼:

	protected void addSingleton(String beanName, Object singletonObject) {
		synchronized (this.singletonObjects) {
			this.singletonObjects.put(beanName, singletonObject);
			this.singletonFactories.remove(beanName);
			this.earlySingletonObjects.remove(beanName);
			this.registeredSingletons.add(beanName);
		}
	}

當然,這個問題的前置還有Spring的bean生命周期系列,回答完后問到這里的。

3、G1對宿主機有什么要求?

這個當時回答不上來,然后也沒找到什么有用的資料;

4、堆設置有什么注意事項?

留出可用空間的20%給元空間。


小米一面

1、手寫Dubbo的加權隨機算法

背景是我簡歷上面寫了深入了解Dubbo,對Dubbo源碼有深入了解,然后面試官就問出了這個問題。比較簡單,寫出的代碼如下:

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class WeightedRandom {

    private static Random random = new Random();

    public static void main(String[] args) {
        List<Node> list = new ArrayList();
        list.add(new Node("節點一(5)",5));
        list.add(new Node("節點二(3)",3));
        list.add(new Node("節點三(2)",2));
        for (int i = 0;i < 10000;i++) {
            Node cur = selected(list);
            // 統計操作
        }
        // 打印結果
    }

    private static Node selected(List<Node> list) {
        if (list == null || list.size() == 0) {
            return null;
        } else if (list.size() == 1) {
            return list.get(0);
        }
        int totalWeight = 0;
        boolean sameWeight = true;
        int firstWeight = 0;
        for (int i = 0;i < list.size();i++) {
            if (i == 0) {
                totalWeight += list.get(0).weight;
                firstWeight = list.get(0).weight;
            } else {
                totalWeight += list.get(i).weight;
                if (list.get(i).weight != firstWeight) {
                    sameWeight = false;
                }
            }
        }
        if (!sameWeight) {
            int curVal = random.nextInt(totalWeight);
            for (int i = 0;i < list.size();i++) {
                curVal -= list.get(i).weight;
                if (curVal < 0) {
                    return list.get(i);
                }
            }
        }

        return list.get(random.nextInt(list.size()));
    }

    private static class Node {
        String name;
        int weight;

        public Node(String name,int weight) {
            this.name = name;
            this.weight = weight;
        }
    }
}

2、Spring獲取代理對象解決事務失效的問題。

調Spring對應的api,這樣做會把框架代碼耦合在自己的業務代碼中;

自己注入自己,需要注意死循環的問題;

盡量避免這種同一個Service中非事務方法調用事務方法的情況。


滴滴二面

1、一個升序數組,隨機選擇一個旋轉節點。右邊的有序段放到左邊,依然保持有序;左邊的有序段放到右邊,依然保持有序。然后從這個數組中查找某個數。

這個問題本質還是找那個旋轉點,當知道那個旋轉點后,無非就是在左邊或者右邊進行二分查找。

當時回答這個問題的主要思路就是從一個數組兩頭開始,分別作為left和right,然后計算中間位置mid,然后在left和mid之間找新的left,在mid和right之間找新的right,不斷逼近從而找出那個旋轉節點,旋轉節點滿足條件:arr[index - 1] > arr[index] > arr[index + 1]。


美團一面

1、Spring和Mybatis是怎么結合的?

這個問題當時沒有理解面試官的意圖,然后回答它們之間有一個整合包,這個整合包充當了一個適配器的角色,然后面試官就沒有再問了。

2、mysql explain有哪些項?

常規問題,比如涉及的表、訪問方法、可能索引、實際使用的索引等。

3、dubbo協議

這一個也是針對簡歷來問的,聽到后心里有點涼快,然后就老實回答自己對於一些核心流程代碼確實看過,但是對於這樣底層的東西確實沒有怎么了解過。

4、單鏈表找循環節點。

leetcode上的常規題了,幾分鍾就搞定了。


小米二面

1、順序讀取一億個整數,找出前100萬大的數字,內存限定大小為10M,后內存限定大小為5M。

我首先回答1個整型在內存中占4個字節,100萬個整數占用4M,然后我在內存中加載200萬個整數分為2個組,排序然后合並選出前100萬大的數字,然后重新讀取100萬個數字繼續同樣的操作。

這時,面試官說將內存限制為5M。

很明顯,就是想問問大頂堆而已,然后就回答使用大頂堆,畢竟返回結果不要求嚴格有序,只要前100萬大就可以了。

小米二面面完后,還有三面的,但是我實在忍受不了那個三面面試官那牛逼哄哄的樣子,所以面到一半我就直接退出會議室了,面了這么多場,遇到了一些態度很好的面試官,也遇到一些態度很差的面試官,就數小米這三面面試官的態度最他么惡心。

在小米三面的時候我就已經拿到自己想要的offer了,所以那天面試也就是抱着聊的好玩的心態聊,並沒想去小米,結果着實把我惡心了。


去哪兒一面

1、stream和foreach區別?

有使用,但是沒有太多了解,就沒有回答出什么。

2、zookeeper和nacos區別?nacos符合CP還是AP?

這個問題印象特別深,原本是沒有看過nacos官方對這一個介紹的,但是看過CAP理論,然后想到即使nacos掛了,nacos客戶端仍然可以通過本地緩存列表繼續工作,所以果斷回答了AP。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM