JavaRush /Java блогу /Random-KY /Бир интервьюнун окуясы: кызыктуу суроолор
GuitarFactor
Деңгээл
Санкт-Петербург

Бир интервьюнун окуясы: кызыктуу суроолор

Группада жарыяланган
Жакында мен ири IT-компаниялардын биринде стажировкадан өтүү үчүн интервьюга катышууга мүмкүнчүлүк алдым. Бир интервьюнун окуясы: кызыктуу суроолор - 1Бул менин биринчи IT интервьюм жана менин оюмча, кызыктуу болду. Бардыгы болуп, мени 3 сааттан ашык "суракка алышты" (анын алдында үй тапшырмасы жана кеңседе компьютерде тест болду). Мен суроого туура эмес жооп бергенде багынбай, анын жетектөөчү суроолорунун жардамы менен мени ойлонууга, туура жоопко келүүгө аргасыз кылган интервьючуга таазим кылгым келет. Төмөндө мен бир нече "эскиздерди" сунуштайм - менин оюмча, абдан кызыктуу суроолор, алардын айрымдары мага Java тorнин айрым аспектилерин тереңирээк түшүнүүгө жардам берди. Балким, бул нерселер кээ бирөөлөргө ачык көрүнөт, бирок менимче, бул пайдалуу боло тургандар болот. Төмөндө фразалар төмөнкү шрифттер менен белгиленет: Интервьючу - коюу менен Үн менен түшүндүрмөлөр жана менин ойлорум - курсив менен Менин жоопторум - кадимки шрифтте Фонду бүтүрүп бүттүк, кел бизнеске киришели)

Эскиз 1. "Жөнөкөй көрүнгөн ыкма"

а санын б санына бөлгөндүн натыйжасын бере турган ыкманы кантип ишке ашырарыңызды жазыңыз.Интервью алуучу кагазга жазат
int divide(int a, int b) {
}
*Мен ыкма кол тамгасы бар кагазга ишене албай карадым. Бул эмне?* Мен мындай деп жазам:
int divide(int a, int b) {
    return a/b;
}
Бул ыкма менен кандайдыр бир көйгөйлөр барбы? *Мен чындап эле келесоо акылсызды кармап жатам* Сыягы, жок . *Оо, мен ушинтип кете берсем, бул кеңседен куулуп чыга жаздадым!* Ооба, албетте. Бул жерде бизде int түрүндөгү аргументтер бар, андыктан Арифметикалык өзгөчөлүк ыргытылат. Эгерде аргументтер float же double тибинде болсо, натыйжа Infinity болмок. Бул тууралуу эмне кылмакчыбыз? Мен аракет/кармап жаза баштадым
int divide(int a, int b) {
    try {
        return a/b;
    } catch (Exception e) {
        e.printStackTrace();
        return ... // ??? what the hack?
    }
}
*Мен кайтып келип, катып калам: ката болгондо бир нерсе кайтарылышы керек. Бирок бул «бир нерсени» эсептин натыйжасынан кантип айырмалоого болот?* Биз эмнени кайтарабыз? Мм... Мен кайтаруучу өзгөрмөнүн түрүн бүтүн санга өзгөртмөкмүн жана өзгөчө учурда мен нөлдү кайтармакмын. Типти өзгөртө албайбыз деп элестетип көрөлү. Кандайдыр бир жол менен чыга алабызбы? Балким, биз башка бир нерсе кыла алабыз? *Мына келди* Биз аны чакыруу ыкмасына да жөнөтө алабыз! Туура. Ал эмнеге окшош болот?
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();
    }
}
Бул өзгөчө мамиле кылуу керекпи? Ооба, анткени биз аны бөлүү ыкмасынан ачык өткөрүп жатабыз. (*Мен бул жерден жаңылганмын! Төмөндө интервьюердин суроолору туура жоопко жетет*) Жана Арифметикалык өзгөчөлүк - бул кандай өзгөчөлүк - текшерилген же белгиленбеген? Бул Runtime бөтөнчөлүгү, такталбаган дегенди билдирет. *Мына киши өлтүргүч суроо келип чыгат* Демек, сиздин сөзүңүз боюнча, эгерде биз кол коюу методунда арифметикалык өзгөчөлүктү көрсөтсөк, анда ал текшерилген өзгөчөлүк болуп калдыбы? *Уф!* Балким... жок. Ооба, кетти. Кол коюуда ыргытууларды /текшерилбеген өзгөчөлүктү/ көрсөтсөк, метод өзгөчөлүктү ыргыта аларын гана эскертебиз, бирок аны чакыруу методунда иштетүү зарыл эмес. Ошол чечилди. Ката кетирбөө үчүн биз кыла турган дагы бир нерсе барбы? *Бир аз ойлонгондон кийин* Ооба, биз да текшере алабыз (b==0). Жана логиканы аткарыңыз. Туура. Ошентип, биз 3 жол менен бара алабыз:
  • аракет кылуу/кармап алуу
  • ыргытат - чакыруу ыкмасына багыттоо
  • аргумент текшерүү
Мындай учурда divideкайсы ыкма артык деп ойлойсуз?
Мен өзгөчө кырдаалды чакыруу ыкмасына жөнөтүүнү тандамакмын, анткени... intбөлүү методунда бул өзгөчөлүктү кантип иштетүү керектиги жана ката болгон учурда кандай натыйжаны кайтаруу керектиги так эмес . Ал эми чакыруу методунда мен аргумент b нөлгө барабар экендигин текшерүү үчүн колдонот элем. Бул жооп интервью алганды канааттандырды окшойт, бирок чынын айтсам, бул жооп бир түшүнүктүү экенине ишенбейм))

Эскиз 2. “Ким тез?”

Стандарттык суроодон кийин, ArrayList LinkedListтен эмнеси менен айырмаланат: Эмне тезирээк болот - элементти ортого ArrayListже ортого киргизүү LinkedList? *Бул жерде мен секирип кеттим, мен бардык жерде " LinkedListтизменин ортосуна элементтерди киргизүү же алып салуу үчүн колдонуу" сыяктуу бир нерсени окуганымды эстедим. Үйдө мен JavaRush лекцияларын эки жолу текшерип көрдүм, мындай сөз бар: "эгерде сиз коллекциянын ортосуна көп элементтерди киргизе турган болсоңуз (же жок кылгыңыз келсе), анда LinkedList. Калган бардык учурларда - ArrayList. Автоматтык түрдө жооп берет* Ал менен ылдамыраак болот LinkedList. Сураныч, тактап бериңиз
  1. Элементти ортого киргизүү үчүн ArrayList, биз тизмедеги элементти туруктуу убакытта табабыз, андан кийин сызыктуу убакытта киргизилген элементтердин оң жагындагы элементтердин индекстерин кайра эсептейбиз.
  2. Үчүн LinkedList.. Биз адегенде сызыктуу убакытта ортого жетебиз, андан кийин кошуна элементтер үчүн шилтемелерди өзгөртүп, туруктуу убакытта элементти киргизебиз.
Демек, кайсынысы тезирээк экен? Хм... Ошол эле болуп чыкты. Бирок качан тезирээк LinkedList? Аны тизменин биринчи жарымына киргизгенибизде. Мисалы, эгер сиз аны эң башында киргизсеңиз, анда сиз ArrayListэң куйругуна чейин бардык индекстерди кайра эсептөөгө туура келет, бирок LinkedListбиринчи элементтин шилтемесин гана өзгөртүүгө туура келет. Моралдык: JavaRushта да жазылгандын баарына ишенбе!)

Эскиз 3. "Теңдештерсиз жана хэшcodeсуз кайда болмокпуз!"

Теңдештер жана хэшcode жөнүндө сүйлөшүү абдан узак болду - аны кантип жокко чыгаруу керек, ичинде кандай ишке ашыруу Object, капоттун астында эмне болот, элементке киргенде HashMapж.б. Мен жөн гана менин оюмча кызыктуу болгон бир катар пункттарды келтирейин* Элестеткиле, биз класс түздүк
public class A {
    int id;

    public A(int id) {
        this.id = id;
    }
}
Жана алар жокко чыгарган жок equalsжана hashcode. Код аткарылганда эмне болорун сүрөттөп бериңиз
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. А классынын эки нускасын түзүңүз

  2. Биз бош картаны түзөбүз, анда демейки боюнча 16 себет бар. Ачкыч А классынын an objectи болуп саналат, анда equalsжана ыкмалары жокко чыгарылbyte hashcode.

  3. Аны a1картага салыңыз. Бул үчүн, биз алгач хэшти эсептейбиз a1.

    Хеш эмнеге барабар болот?

    Эс тутумдагы уячанын дареги класстын методун ишке ашыруу болуп саналатObject

  4. Хештин негизинде биз себеттин индексин эсептейбиз.

    Аны кантип эсептесек болот?

    *Тилекке каршы, мен бул жерде так жооп берген жокмун. Сизде узун сан бар - хэш жана 16 чака бар - ар кандай хэштери бар an objectтер чакаларга бирдей бөлүштүрүлүшү үчүн индексти кантип аныктоо керек? Мен индекс төмөнкүдөй эсептелет деп элестете алам:

    int index = hash % buckets.length

    Үйдө мен булак codeундагы баштапкы ишке ашыруу бир аз башкача экенин көрдүм:

    static int indexFor(int h, int length)
    {
        return h & (length - 1);
    }
  5. Биз кагылышуулар жок экенин текшерип, a1 киргизебиз.

  6. Келгиле, ыкмага өтөбүз get. a1 жана a2 инстанциялары башка (эстутумдагы башка дарекке) ээ болот hash, ошондуктан бул ачкыч үчүн эч нерсе таба албайбыз

    Эгер биз аны hashcodeА классында гана аныктап, хэшмапка а1 ачкычы менен жупту, анан a2 менен киргизүүгө аракет кылсакчы?

    Андан кийин алгач биз каалаган себетти табабыз hashcode- бул операция туура аткарылат. EntryАндан кийин, арабага тиркелген LinkedList ичиндеги an objectтерди карап баштайлы жана ачкычтарды менен салыштырып көрөлү equals. Анткени equalsжокко чыгарылbyte, анда базалык ишке ашыруу класстан алынат Object- шилтеме боюнча салыштыруу. a1 жана a2 ар кандай шилтемелерге ээ болууга кепилдик берилет, ошондуктан биз киргизилген a1 элементин “сагынып” калабыз жана a2 LinkedListке жаңы түйүн катары жайгаштырылат.

    Жыйынтык кандай? HashMapАчкыч катары an objectте жокко чыгарылбаган менен колдонууга болобу equalshashcode?

    Жок болбойт.

Эскиз 4. "Атайылап сындыралы!"

Ката жана өзгөчө кырдаал жөнүндөгү суроолордон кийин төмөнкү суроо пайда болду: Функция StackOverflow ыргыта турган жөнөкөй мисал жазыңыз. *Андан кийин мен кандайдыр бир рекурсивдүү функцияны жазууга аракет кылып жатканда бул ката мени кандай кыйнаганын эстедим* Бул рекурсивдүү чалуу учурунда, рекурсиядан чыгуунун шарты туура эмес көрсөтүлсө болот. *Андан кийин мен бир аз акылдуу боло баштадым, аягында маектешим жардам берди, баары жөнөкөй болуп чыкты*
void sof() {
    sof();
}
Бул катадан эмнеси менен айырмаланат OutOfMemory? *Мен бул жерде жооп берген жокмун, кийинчерээк бул Java эстутумун билүү жөнүндө суроо экенин түшүндүм Stack( Heapan objectтерге чалуулар жана шилтемелер Стекте сакталат, ал эми an objectтердин өзү үймөк эстутумда сакталат). StackТиешелүү, StackOverflow кийинки ыкма чакыруусу үчүн эстутумда бош орун калбай калганда ыргытылат жана OutOfMemoryan objectтер үчүн орун эстутумда түгөнүп калган Heap*
Бул интервьюдан менин эсимде калган көз ирмемдер. Акырында стажировкага кабыл алындым, ошондуктан алдыда 2,5 ай окуу, эгер баары ойдогудай болсо, компанияда жумуш бар) Кызыкчылык болсо, дагы бир макала жазсам болот, бул жолу кичирээк, башка компанияда мага интервью берген жөнөкөй, бирок иллюстрациялуу маселенин анализи. Мунун баары мен үчүн, бул макала кимдир бирөөнүн бorмин тереңдетүүгө же уюштурууга жардам берет деп ишенем. Баарыңарга бактылуу окуу!
Комментарийлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION