京东-零售-数据研发面经【附答案】
近期,有参加春招的同学和我交流了他的面试历程,我针对这些内容进行了细致的总结与梳理,并在此分享出来,希望能助力大家学习与借鉴。
1.八股文
1)HashMap的底层原理是什么【见V6.0面试笔记 Java基础部分第19题】
2)了解MapReduce的combine和merge吗【见V6.0面试笔记 MapReduce部分第1题】
3)Hive分区和分桶的区别是什么以及适用的场景分别是什么【见V6.0面试笔记 Hive部分第5题】
4)Hive/Spark是如何构建UDF的【见V6.0面试笔记 Hive部分第14题】
面试笔记补充:Spark是如何构建UDF的?【补充至 Spark补充题第26题】
// 1.定义UDF(获取字符串的最后一个字符)
def strLastChar(col: String) = {
str.last
}
// 2.注册UDF
spark.udf.register("strLastChar", strLastChar _)
// 3.使用UDF
spark.sql("select name, strLastChar(name) from tmp")
5)Spark中job、stage、task之间的关系是什么【见V6.0面试笔记 Spark部分第6题】
6)Spark中CheckPoint、Cache、Persist的区别是什么【见V6.0面试笔记 Spark部分第14题】
7)你执行Spark任务时是如何确定Executor的数量、核数以及内存大小的【见V6.0面试笔记 Spark部分第4题】
面试笔记补充:如何确定Executor的数量、核数以及内存大小的?【补充至 Spark补充题第27题】
- Executor数量(num-excutors):集群总CPU核心数 / excutor-cores;官网推荐50~100
- Executor核心数(excutor-cores):官网推荐 2~4 核心数
- Executor内存(excutor-memory):官网推荐 4G~8G
8)HBase一般适用于什么场景使用【见V6.0面试笔记 HBase部分第2题】
9)你用过ElasticSearch吗,简单介绍一下
Elasticsearch 是一个开源的分布式搜索引擎,分布式体现在将数据存储在多个节点上,这些节点之间形成一个集群,数据会被分成多个分片(shards),每个分片可以有多个副本(replicas),用来保证数据的高可用性;搜索使用一种倒排索引(inverted index)的数据结构,将文本中的单词与其出现的文档位置相关联,从而实现快速的搜索。
10)了解ElasticSearch的倒排索引吗
倒排索引是一种索引结构,它将文档中的单词映射到包含这些单词的文档集合,与传统的正向索引(将文档映射到单词列表)不同,倒排索引反转了这种关系,能够快速定位到包含特定单词的文档。我简单介绍一下它的原理,首先将文档的文本内容通过分词器分割成单词,然后为每个分词后的单词构建其对应的倒排列表,在 Elasticsearch 中,倒排索引是自动构建和维护的。在搜索时,系统根据查询关键词查找倒排索引,快速定位包含这些关键词的文档
2.项目
1)介绍一个你觉得做得最好的项目
2)你认为其中的难点在哪里
3)举一个你曾经遇到过的最难写的代码的例子
3.刷题
SQL题
题目: 有一张某日若干A股交易流水表dwd_trd_stock_price_log,包含s_code(股票代码)、price(交易价格)、ds(交易时间),计算当天股票交易能够达到的最大利润
参考答案:
select
s_code,
max(profit) as max_profit
from
(
select
s_code,
price - min_price as profit
from
(
select
s_code,
price,
min(price) over(
partition by
s_code
order by
STR_TO_DATE(ds, '%Y-%m-%d %H:%i')
) as min_price
from
dwd_trd_stock_price_log
) t
) t
group by
s_code;
算法题
题目: 正则表达式匹配 (LeetCode第10题)
参考答案:
class Solution {
public boolean isMatch(String s, String p) {
int m = s.length(), n = p.length();
boolean[][] dp = new boolean[m + 1][n + 1]; // +1 为了方便处理边界
// dp初始化
dp[0][0] = true;
for (int i = 1; i < m + 1; i++) {
dp[i][0] = false; // 空的匹配串,是匹配不上字符的
}
for (int i = 1; i < n + 1; i++) { // a* 是可以匹配上空字符的
if (p.charAt(i - 1) == '*')
dp[0][i] = dp[0][i - 2];
else
dp[0][i] = false;
}
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (p.charAt(j - 1) == '*') {
if (isMatch(s, p, i, j - 1)) {
dp[i][j] = dp[i][j - 2] || dp[i - 1][j];
} else { // 使用*
dp[i][j] = dp[i][j - 2];
}
} else {
dp[i][j] = dp[i - 1][j - 1] && isMatch(s, p, i, j);
}
}
}
return dp[m][n];
}
private static boolean isMatch(String s, String p, int i, int j) {
return s.charAt(i - 1) == p.charAt(j - 1) || p.charAt(j - 1) == '.';
}
}