JavaRush /Java 博客 /Random-ZH /一次采访的故事:有趣的问题
GuitarFactor
第 30 级
Санкт-Петербург

一次采访的故事:有趣的问题

已在 Random-ZH 群组中发布
最近我有机会参加一家大型IT公司实习生的面试。 一次采访的故事:有趣的问题 - 1这是我的第一次 IT 面试,在我看来,它很有趣。总共,我被“审问”了3个多小时(之前有作业和在办公室电脑上进行的测试)。我要向面试官致敬,当我回答错误的时候,他并没有放弃,而是在他的引导性问题的帮助下迫使我思考并得出正确的答案。下面我将提出几个“草图”——在我看来,相当有趣的问题,其中一些让我对 Java 的某些方面有了更深入的了解。也许这些事情对某些人来说似乎是显而易见的,但我认为这对某些人来说是有用的。下面的短语以下列字体突出显示: 采访者 - 粗体 画外音解释和我的想法 - 斜体 我的答案 - 采用常规字体 我们已经完成了背景知识,让我们开始进入正题吧)

草图 1.“看似简单的方法”

写下如何实现一个返回数字 a 除以数字 b 的结果的方法。 面试官写在一张纸上
int divide(int a, int b) {
}
*我难以置信地看了一眼带有方法签名的纸。有什么问题?*我写道:
int divide(int a, int b) {
    return a/b;
}
这个方法有什么问题吗? *我抓住了一个非常愚蠢的笨蛋* 显然不是.. 接下来是一个合理的问题: 如果b=0怎么办? *哇哦,如果我再这样下去,我就要被赶出这个办公室了!* 哦,是的,当然。这里我们有 int 类型的参数,因此会抛出算术异常。如果参数的类型为 float 或 double,则结果将为 Infinity。 对此我们该怎么办? 我开始写try/catch
int divide(int a, int b) {
    try {
        return a/b;
    } catch (Exception e) {
        e.printStackTrace();
        return ... // ??? what the hack?
    }
}
*我要返回并冻结:如果出现错误,需要返回一些东西。但如何才能将这个“东西”与计算结果区分开来呢?* 我们会返回什么? 嗯...我会将返回变量的类型更改为 Integer,如果出现异常,我将返回 null。 假设我们无法更改类型。我们能以某种方式出去吗?也许除了例外我们还可以做点别的事? *来了* 我们还可以将它转发给调用方法! 正确的。它会是什么样子?
int divide(int a, int b) throws ArithmeticException{
    return a/b;
}

void callDivide(int a, int b) {
    try {
        divide(a, b);
    } catch (ArithmeticException e) {
        e.printStackTrace();
    }
}
是否需要处理异常? 是的,因为我们明确地从divide方法中转发它。(*我错了!接下来是面试官提出的引导性问题,以得出正确答案*) 算术异常 - 它是什么样的异常 - 检查或未检查? 这是一个运行时异常,这意味着未经检查。 *杀手问题来了* 所以,用你的话来说,如果我们在方法签名中指定 throws Arithmetic Exception,那么它就变成了检查异常? *呃!* 可能...不。 是的,没有。如果我们在签名中指明 throws /unchecked exception/ ,我们只是警告该方法可以抛出异常,但不需要在调用方法中处理它。就这么解决了 我们还能做些什么来避免错误吗? *经过一番思考* 是的,我们还可以检查 if (b==0)。并执行一些逻辑。 正确的。所以我们可以采取三种方式:
  • 试着抓
  • throws – 转发到调用方法
  • 参数检查
在这种情况下,divide您认为哪种方法更可取?
我会选择将异常转发给调用方法,因为...... 在divide方法中,尚不清楚如何处理此异常以及int发生错误时返回什么类型的结果。在调用方法中,我将使用参数 b 来检查它是否等于零。 看来这个答案让受访者满意了,但说实话,我不确定这个答案是否明确))

草图 2.“谁更快?”

在标准问题“ArrayList 与 LinkedList 有何不同”之后,出现了以下问题: 会发生什么更快 - 将元素插入到中间ArrayList还是插入到中间LinkedList *我跳到这里,我记得我到处都读到过类似“用于LinkedList在列表中间插入或删除元素”之类的内容。在家里我什至仔细检查了JavaRush讲座,有这样一句话:“如果你要在集合中间插入(或删除)许多元素,那么你最好使用LinkedList. 在所有其他情况下—— ArrayList” 自动应答* 使用 会更快LinkedList请澄清一下
  1. 为了在中间插入一个元素ArrayList,我们需要在常数时间内找到列表中的元素,然后在线性时间内重新计算要插入的元素右侧元素的索引。
  2. 对于LinkedList..我们首先在线性时间内到达中间,然后在恒定时间内插入一个元素,改变相邻元素的链接。
事实证明,哪个更快? 嗯……结果是一样的。 但什么时候LinkedList更快呢? 事实证明,当我们将它插入到列表的前半部分时。例如,如果您将其插入到最开头,则ArrayList必须重新计算直到最尾部的所有索引,但只需LinkedList更改第一个元素的引用。 寓意:不要相信字面上所写的所有内容,即使是 JavaRush 中的内容!)

草图 3:“如果没有 equals 和 hashcode,我们会怎么样!”

关于 equals 和 hashcode 的对话非常长 - 如何覆盖它、 中的实现是什么Object、幕后发生了什么、何时将元素插入HashMap等。我只会给出一些我认为有趣的观点* 想象一下我们创建了一个类
public class A {
    int id;

    public A(int id) {
        this.id = id;
    }
}
他们并没有覆盖equalshashcode。描述代码执行时会发生什么
A a1 = new A(1);
A a2 = new A(1);
Map<A, String> hash = new HashMap<>();
hash.put(a1, "1");
hash.get(a2);
*很好的是,在面试之前我专门花了几天时间了解基本算法、它们的复杂性和数据结构 - 这很有帮助,感谢 CS50!*
  1. 创建 A 类的两个实例

  2. 我们创建一个空地图,默认情况下有 16 个篮子。关键是 A 类的对象,其中 和equals方法未被重写hashcode

  3. 把它a1放在地图上。为此,我们首先计算哈希值a1

    哈希值等于什么?

    内存中单元的地址是类方法的实现Object

  4. 根据哈希值,我们计算篮子指数。

    我们如何计算呢?

    *不幸的是,我在这里没有给出明确的答案。你有一个很长的数字——一个哈希值,并且有16个桶——如何定义一个索引,使得具有不同哈希值的对象均匀分布在桶中?我可以想象该指数是这样计算的:

    int index = hash % buckets.length

    我已经在家里看到源代码中的原始实现略有不同:

    static int indexFor(int h, int length)
    {
        return h & (length - 1);
    }
  5. 我们检查没有冲突并插入 a1。

  6. 让我们继续讨论方法get。实例 a1 和 a2 保证具有不同的hash(内存中不同的地址),因此我们不会找到该键的任何内容

    如果我们只hashcode在 A 类中重新定义它,并尝试先将一对键值是 a1,然后是 a2 的键值对插入到 hashmap 中,会怎么样?

    然后首先我们将通过以下方式找到所需的篮子hashcode- 此操作将正确执行。接下来,让我们开始浏览Entry附加到购物车的 LinkedList 中的对象,并通过 比较键equals。因为 equals不被覆盖,则从类中获取基本实现Object- 通过引用进行比较。a1和a2保证有不同的链接,因此我们会“错过”插入的元素a1,而a2将作为新节点放入LinkedList中。

    结论是什么?是否可以将其用作HashMap非重写对象中的键equalshashcode

    你不能。

草图4:“我们故意打破它吧!”

在有关错误和异常的问题之后,接下来的问题如下: 编写一个简单的示例,其中函数将抛出 StackOverflow。 *然后我记得当我尝试编写一些递归函数时,这个错误如何困扰我* 如果错误地指定了退出递归的条件,则在递归调用的情况下,可能会发生这种情况。 *然后我开始尝试一些聪明的事情,最后面试官帮忙了,一切变得简单*
void sof() {
    sof();
}
这个错误与 有何不同OutOfMemory *这里我没有回答,后来才知道这是一道关于Java内存知识Stack的问题Heap(对象的调用和引用都存储在Stack中,对象本身存储在Heap内存中)。因此,当内存中没有更多空间可供Stack下一个方法调用,并且OutOfMemory内存中对象的空间已用完时,StackOverflow 就会被抛出Heap*
这些是我记得的采访时刻。最后,我被接受了实习,所以我还有2.5个月的培训时间,如果一切顺利的话,我会在公司找到一份工作)如果有兴趣,我可以再写一篇文章,这次较小,对我在另一家公司面试时遇到的一个简单但具有说明性的问题进行了分析。这就是我的全部内容,我希望这篇文章能帮助人们加深或组织他们的知识。大家学习愉快!
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION