Je sice hezké, že znáš poslední módu v Javě, ale inženýrská praxe na tomto nestojí.
Nechcel som sa k tomu vracať, ale ešte raz to skúsim zhrnúť. Pán stiahol nejaký chyták z netu (spolu s NPE chybou) a dal ju ako test uchádzačovi. Dá sa nájsť napr.
https://www.programcreek.com/2014/05/top-10-mistakes-java-developers-make/ (Dokonca aj to názvoslovie je skopírované
A potom to dal chudákovi uchádzačovi ako príklad na papieri. Tiež zmenil zadanie z
Remove an Element from a List Inside a Loop na hmlisté
jestli se mu to libi. A jestli ne, tak co by udelal jinak.ArrayList<String> words = new ArrayList(Arrays.asList("pen", "pencil",
"sky", "blue", "sky", "dog"));
Iterator<String> iter = words.iterator();
while (iter.hasNext()) {
String s = iter.next();
if ("sky".equals(s)) {
iter.remove();
}
}
System.out.println(words);
Ako riešenie sa uvádza použitie iterátora, pretože s for cyklom dochádza ku
ConcurrentModificationException.
Lenže oproti použitiu funkcionálnej Javy je toto riešenie inferiórne.
List<String> words = List.of("hello", "sky", "there", "den", "sky");
List<String> words2 = words.stream().filter(e -> !e.equals("sky")).collect(Collectors.toList());
System.out.println(words2);
Toto riešenie je omnoho lepšie. Je to okrem iného rozdiel v internej a externej iterácii, kde tá interná má veľa výhod oproti externej. Napríklad v tom, že ja sa nemusím starať o takúto chybu (
ConcurrentModificationException), lebo k nej nedôjde. Je to non-issue.
Viď rozdiely medzi internou a externou iteráciou:
https://www.linkedin.com/pulse/java-8-external-iterator-vs-internal-saral-saxenaSimplified implementation/less defects as code written by programmer is very less, chances of bugs creeping into the iteration logic are not there.
Nie som prvý, ktorý na takýto typ problému navrhujú funkcionálny prístup. Keď toto riešili Python programátori
https://stackoverflow.com/questions/1207406/how-to-remove-items-from-a-list-while-iteratinga JavaScript programátori, tak funkcionálne riešenie získalo kladné ohlasy.
https://stackoverflow.com/questions/9882284/looping-through-array-and-removing-items-without-breaking-for-loopJa som si tu vyslúžil naopak zhadzovanie.
Je zaujímavé tiež, že v Jave spätná externá iterácia s mazaním funguje.
List<String> words = new ArrayList<>(Arrays.asList("pen", "pencil",
"sky", "blue", "sky", "dog"));
for (int i=words.size() - 1; i>=0; i--) {
if ("sky".equals(words.get(i))) {
words.remove(i);
}
}
System.out.println(words);
Pozn. 2: k té změně seznamu při procházení - padlo tu, že se to netýká jen Javy. Ale na to musím reagovat, že to obecně žádná chyba není - může, jako třeba tady, ale taky nemusí. Dokonce v základní algoritmické podobě odstranit prvek zadaný jeho hodnotou ze seznamu ani jinak nejde než při jeho procházení.
Veľmi dobrá poznámka. Takáto externá iterácia funguje napr. v Python 3 a Perl 6.
#!/usr/bin/perl6
my @letters = <pen pencil dog sky blue sky>;
loop (my $i = 0; $i < @letters.elems; $i++) {
if (@letters[$i] eq "sky") {
@letters.splice($i, 1);
}
}
say @letters;
say @letters.elems;
Toto je príklad v Perl 6, kde takýto kód funguje.
#!/usr/bin/python3
words = ["pen", "pencil", "dog", "sky", "blue", "sky"]
print(len(words))
for word in words:
if word == "sky":
words.remove(word)
print(words)
print(len(words))
# funkcionalne
words = ("pen", "pencil", "dog", "sky", "blue", "sky")
words2 = [e for e in words if not e == "sky"]
print(words2)
print(len(words2))
Toto je kód v Python 3. Takisto funguje externá iterácia s mazaním. Funkcionálny prístup je však lepší.
Používanie chytákov stiahnutých niekde z netu, bez možnosti použitia počítača, len tak na papieri je neprofesionálne a voči uchádzačom neférové. To každý vie byť frajer a stiahnuť si nejaký príklad, ktorý vás nachytá na obskúrnej časti jazyka.