JavaRush /Java Blog /Random EN /The story of one interview: interesting questions
GuitarFactor
Level 30
Санкт-Петербург

The story of one interview: interesting questions

Published in the Random EN group
Recently I had the opportunity to attend an interview for an intern position in one of the large IT companies. The story of one interview: interesting questions - 1This was my first IT interview and, in my opinion, it turned out to be interesting. In total, I was “interrogated” for more than 3 hours (this was preceded by homework and a test in the office on a computer). I want to pay tribute to the interviewer, who did not give up when I answered the question incorrectly, but with the help of his leading questions forced me to think about it and come to the correct answer. Below I will present several “sketches” - in my opinion, quite interesting questions, some of which gave me a deeper understanding of certain aspects in Java. Perhaps these things will seem obvious to some, but I think there will be those for whom this will be useful. Below the phrases are highlighted in the following fonts: Interviewer - in bold Voice-over explanations and my thoughts - in italics My answers - in regular font We’re done with the background, let’s get down to business)

Sketch 1. “A seemingly simple method”

Write how you would implement a method that returns the result of dividing number a by number b. The interviewer writes on a piece of paper
int divide(int a, int b) {
}
*I glanced incredulously at the piece of paper with the method signature. What's the catch?* I write:
int divide(int a, int b) {
    return a/b;
}
Are there any problems with this method? *I'm catching a really stupid dumbass* Apparently not.. Next comes a legitimate question: What if b=0? *Whoa, I'm about to be kicked out of this office if I continue like this!* Oh yes, of course. Here we have arguments of type int, so an Arithmetic Exception will be thrown. If the arguments were of type float or double, the result would be Infinity. What are we going to do about this? I'm starting to write try/catch
int divide(int a, int b) {
    try {
        return a/b;
    } catch (Exception e) {
        e.printStackTrace();
        return ... // ??? what the hack?
    }
}
*I get to return and freeze: something needs to be returned in case of an error. But how can this “something” be distinguished from the result of the calculation?* What will we return? Hm... I would change the type of the return variable to Integer and in case of an exception I would return null. Let's imagine that we can't change the type. Can we somehow get out? Maybe we can do something else with the exception? *Here it comes* We can also forward it to the calling method! Right. What will it look like?
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();
    }
}
Is it necessary to handle the exception? Yes, because we explicitly forward it from the divide method. (*I was wrong here! What follows are leading questions from the interviewer to arrive at the correct answer*) And Arithmetic Exception - what kind of exception is it - checked or unchecked? This is a Runtime exception, which means unchecked. *Here comes the killer question* So it turns out, in your words, if we specified throws Arithmetic Exception in the method signature, then it became a checked exception? *Ugh!* Probably... no. Yes, it's gone. If we indicate throws /unchecked exception/ in the signature, we only warn that the method can throw an exception, but it is not necessary to handle it in the calling method. That's sorted out. Is there anything else we can do to avoid mistakes? *After some thought* Yes, we can also check if (b==0). And perform some logic. Right. So we can go 3 ways:
  • try/catch
  • throws – forwarding to the calling method
  • argument checking
In this case, dividewhich method do you think is preferable?
I would choose to forward the exception to the calling method, because... in the divide method it is not clear how to process this exception and what type of result intto return in case of an error. And in the calling method, I would use the argument b to check if it is equal to zero. It seems that this answer satisfied the interviewee, but to be honest, I’m not sure that this answer is unambiguous))

Sketch 2. “Who is faster?”

After the standard question, how does an ArrayList differ from a LinkedList, came this: What will happen faster - inserting an element into the middle ArrayListor into the middle LinkedList? *Here I jumped, I remembered that everywhere I read something like “use LinkedListto insert or remove elements in the middle of the list.” At home I even double-checked the JavaRush lectures, there is a phrase: “if you are going to insert (or delete) many elements into the middle of a collection, then you better use LinkedList. In all other cases - ArrayList.” Automatically answered* It will be faster with LinkedList. Clarify please
  1. In order to insert an element in the middle ArrayList, we find the element in the list in constant time, and then recalculate the indices of the elements to the right of the inserted one, in linear time.
  2. For LinkedList.. We first reach the middle in linear time and then insert an element in constant time, changing links for neighboring elements.
So it turns out, which is faster? Hm... It turns out the same. But when is it LinkedListfaster? It turns out that when we insert it into the first half of the list. For example, if you insert it at the very beginning, you ArrayListwill have to recalculate all the indices up to the very tail, but you LinkedListwill only have to change the reference of the first element. Moral: do not believe literally everything that is written, even in JavaRush!)

Sketch 3. “Where would we be without equals and hashcode!”

The conversation about equals and hashcode was very long - how to override it, what implementation in Object, what happens under the hood, when an element is inserted into HashMap, etc. I will just cite a number of points that are interesting in my opinion* Imagine that we have created a class
public class A {
    int id;

    public A(int id) {
        this.id = id;
    }
}
And they didn't override equalsand hashcode. Describe what will happen when the code is executed
A a1 = new A(1);
A a2 = new A(1);
Map<A, String> hash = new HashMap<>();
hash.put(a1, "1");
hash.get(a2);
*It’s good that before the interview I specifically spent a couple of days understanding the basic algorithms, their complexity and data structures - it helped a lot, thanks CS50!*
  1. Create two instances of class A

  2. We create an empty map, which by default has 16 baskets. The key is an object of class A, in which the equalsand methods are not overridden hashcode.

  3. Put it a1in the map. To do this, we first calculate the hash a1.

    What will the hash be equal to?

    The address of a cell in memory is an implementation of a method from a classObject

  4. Based on the hash, we calculate the basket index.

    How can we calculate it?

    *Unfortunately, I did not give a clear answer here. You have a long number - a hash, and there are 16 buckets - how to define an index so that objects with different hashes are evenly distributed across the buckets? I could imagine that the index is calculated like this:

    int index = hash % buckets.length

    Already at home I saw that the original implementation in the source code is slightly different:

    static int indexFor(int h, int length)
    {
        return h & (length - 1);
    }
  5. We check that there are no collisions and insert a1.

  6. Let's move on to the method get. Instances a1 and a2 are guaranteed to have a different hash(different address in memory), so we will not find anything for this key

    What if we redefine it only hashcodein class A and try to insert into the hashmap first a pair with key a1, and then with a2?

    Then first we will find the desired basket by hashcode- this operation will be performed correctly. Next, let's start going through the objects Entryin the LinkedList attached to the cart and compare the keys by equals. Because equalsis not overridden, then the base implementation is taken from the class Object- comparison by reference. a1 and a2 are guaranteed to have different links, so we will “miss” the inserted element a1, and a2 will be placed in the LinkedList as a new node.

    What is the conclusion? Is it possible to use it as a key in HashMapan object with non-overridden equalshashcode?

    No you can not.

Sketch 4. “Let’s break it on purpose!”

After the questions about Error and Exception, the following question followed: Write a simple example where a function will throw StackOverflow. *Then I remembered how this error plagued me when I was trying to write some recursive function* This will probably happen in the case of a recursive call, if the condition for exiting the recursion is incorrectly specified. *Then I began to try something clever, in the end the interviewer helped, everything turned out to be simple*
void sof() {
    sof();
}
How is this error different from OutOfMemory? *I didn’t answer here, only later I realized that this was a question about knowledge Stackof HeapJava memory (calls and references to objects are stored in the Stack, and the objects themselves are stored in Heap memory). Accordingly, StackOverflow is thrown out when there is no more space in Stackmemory for the next method call, and OutOfMemorythe space for objects has run out in Heapmemory*
These are the moments from the interview that I remember. In the end, I was accepted for an internship, so I have 2.5 months of training ahead of me and, if everything goes well, a job in the company) If there is interest, I can write another article, this time smaller, with an analysis of a simple but illustrative problem that I was given an interview at another company. That's all for me, I hope this article will help someone deepen or organize their knowledge. Happy learning everyone!
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION