Nietypowy problem z nauką Java

0

Cześć,
mam troszkę chyba nietypowy problem. Chcę nauczyć się programować w języku Java, ale nie potrafię się przekonać do samego kodu. Uczę się samodzielnie Pythona od dwóch lat i patrząc na różne przykłady gdzieś w sieci mimowolnie zaczynam zastanawiać się jak to napisać w Pythonie. I to jest mój problem. W książce, którą czytam ("Java w 21 dni" Rogers Cadenhead) jest przykładzik który ma coś wydrukować. Przepisując kod z książki do repl.it wywaliło nawet errora, ale że nie lubię się poddawać to wypatrzyłem gdzie jest źle i poprawiłem błąd. Nazwa klasy była inna, która występowała także poniżej w metodzie. Działa. Tyle tylko, że tak naprawdę nie potrafię zrozumieć tego kodu. Wygląda on tak:

class Main {
  int[] makeRange(int lower, int upper) {
    int[] range = new int[(upper-lower) + 1];

    for (int i = 0; i < range.length; i++) {
      range[i] = lower++;
    }
    return range;
  }
  public static void main(String[] arguments) {
    int[] range;
    Main lister = new Main();
    range = lister.makeRange(4,13);
    System.out.print("Tablica: [ ");
    for (int i = 0; i < range.length; i++) {
      System.out.print(range[i] + " ");
    }
    System.out.println("]");
  }
}

Natomiast dokładnie to samo w Pythonie zajmuje znacznie mniej:

class RangeNums():
  def __init__(self, nums):
    self.nums = nums

  nums = [x for x in range(4,14)]
  str_nums = " ".join([str(x) for x in nums])
  print("Tablica: [ " + str_nums + " ]")

Wiem, głupia sprawa, ale czy jest jakiś sposób, żeby się przekonać do zapisu Javy i samego języka? Chciałbym się nauczyć nie myśleć Pythonem .. jakby to nie zabrzmiało ;)

1

Najpierw zapodaj sobie bibliotekę z rozsądnymi kolekcjami :)

Z http://www.vavr.io/ przykład wygląda tak:

import io.vavr.collection.Iterator;
import static java.lang.System.out;

public class MkStringVavr {
    public static void main(String[] args) {
        Iterator<Integer> nums = Iterator.range(4, 14);
        String strNums = nums.mkString(" ");
        out.println("Tablica: [" + strNums + "]");
    }
}

i to bez słówka kluczowego var, które weszło w Javie 10. Z nim byłoby jeszcze krócej.

Vavr.io jednak nie jest kompatybilne wprost z kolekcjami Javowymi (potrzeba konwersji między nimi), więc jeśli chcesz zachować pełną kompatybilność ze standardowymi kolekcjami Javowymi to zostają biblioteki typu Google Guava. Wtedy kod wygląda tak:

import com.google.common.base.Joiner;

import java.util.Iterator;
import java.util.stream.IntStream;

import static java.lang.System.out;

public class MkStringGuava {
    public static void main(String[] args) {
        Iterator<Integer> nums = IntStream.range(4, 14).iterator();
        String strNums = Joiner.on(' ').join(nums);
        out.println("Tablica: [" + strNums + "]");
    }
}

Java to jednak mimo wszystko głównie (skomplikowane) abstrakcje obiektowe i w takich zastosowaniach generowanie przedziału liczb całkowitych jest dość rzadkim problemem.

1

Bez vavra też się da.

String numbs = Stream
                  .iterate(4, i -> i += 1)
                  .limit(10)
                  .map( x -> x.toString() + " ")
                  .collect(joining(" "));
System.out.println("Tablica: [ " + numbs + "]");

Jak ktoś myśli że Java jest trudna i trzeba się przy niej namęczyć, to niech przez chwilę popiszę w C/C++ - szybko zmieni zdanie (a tak mi się przynajmniej zdaje) :P.

1

Wersja #3, bez dodatkowych bibliotek:

import static java.lang.System.out;
import static java.util.stream.Collectors.joining;
import static java.util.stream.IntStream.range;

public class MkString {
    public static void main(String[] args) {
        String strNums = range(4, 14)
                .mapToObj(i -> "" + i)
                .collect(joining(" ", "Tablica: [", "]"));
        out.println(strNums);
    }
}
0

Chyba źle napisałem posta, albo czytający mają problem ze zrozumieniem czytanego tekstu.

Mi najbardziej chodziło o znalezienie odpowiedzi na pytania, a nie o analizę kodu.

0

No ale jaka jest odpowiedź na to pytanie? Pokazaliśmy Ci, ze w Javie da się to zrobić bardzo prosto i zgrabnie. A że jestes początkujący w Javie, to twoj kod wygląda jak kod początkującego. Jak chcesz się przekonać do kodu Javy, to po prostu w niej pisz, z czasem będzie lepiej.

1

@exec1905:
A jaki jest konkretnie problem? Jak na razie to wygląda jakbyś próbował w Javie wymyślać koło od nowa zamiast użyć metod znajdujących się w bibliotece standardowej i/lub w popularnych zewnętrznych bibliotekach Javowych (jak np Google Guava czy Apache Commons). W Pythonie też namiętnie korzysta się z zewnętrznych bibliotek i/ lub importuje metody z biblioteki standardowej, które nie są domyślnie zaimportowane. Ograniczanie się tylko do domyślnie zaimportowanych metod byłoby... hmm... ograniczające. Najpierw poznawaj metody z biblioteki standardowej. Sam widzisz, że za ich pomocą można pisać w miarę zwięzły kod. Jak już poznasz bibliotekę standardową to możesz dorzucić do tego wspomnianą https://github.com/google/guava czy https://commons.apache.org/

0

Piszesz w wątku Java a nie Newbie - pewnie dlatego takie odpowiedzi ;-)

Kod jest podstawowy, nie wiem co jest niezrozumiałe.

Tyle tylko, że tak naprawdę nie potrafię zrozumieć tego kodu. Wygląda on tak:

class Main {                                                       // deklaracja klasy
  int[] makeRange(int lower, int upper) {            // deklaracja metody
    int[] range = new int[(upper-lower) + 1];        // stworzenie tablicy o określonej ilości elementów

    for (int i = 0; i < range.length; i++) {               // pętla działająca na tablicy
      range[i] = lower++;                                      //  wypełnienie tablicy kolejnymi wartościami od lower do upper
    }
    return range;                                                  // tablica zwracana z metody
  }
  public static void main(String[] arguments) {   // główny program
    int[] range;                                      // tablica bez określenia ilości elementów
    Main lister = new Main();                // stworzenie obiektu klasy Main
    range = lister.makeRange(4,13);    // wypełnienie tablicy przez wywołanie metody makeRange 
                                                            // obiektu (lister) klasy Main
    System.out.print("Tablica: [ ");        // wydruk na konsolę bez znaku nowej lini
    for (int i = 0; i < range.length; i++) {
      System.out.print(range[i] + " ");
    }
    System.out.println("]");                        // zamknięcie lini
  }
}
2

Chciałbym się nauczyć nie myśleć Pythonem

To jest pewien mankament nauki Pythona jako pierwszego języka. Bo to jest język bardzo wysokopoziomowy i "ukrywa" wiele rzeczy przed tobą. Pozwala to oczywiscie na szybką naukę np. algorytmów, bo skupiasz się na samym problemie a nie na "technikaliach", ale potem próba wskoczenia w języki trochę niższego poziomu jest bolesna. Jeszcze z Javą to pół biedy, ale jakbyś spróbował przeskoczyć na C to byłoby to jak zderzenie ze ścianą. Przejscie w drugą stronę jest dużo łatwiejsze bo nagle pewne rzeczy robią się "łatwiejsze".

Natomiast dokładnie to samo w Pythonie zajmuje znacznie mniej:

Nie, to nie jest dokładnie to samo. Dokładnie to samo to by było:

import sys


class Main:
    def makeRange(self, lower, upper):
        rangeList = [None] * ((upper - lower) + 1)
        for i in range(len(rangeList)):
            rangeList[i] = lower
            lower += 1
        return rangeList


def main():
    lister = Main()
    rangeList = lister.makeRange(4, 13)
    sys.stdout.write("Tablica: [ ")
    for i in range(len(rangeList)):
        sys.stdout.write(str(rangeList[i]) + " ")
    sys.stdout.write("]")

main()

I nie jest ani specjalnie krótsze ani bardziej czytelne. A jak już udowodnili koledzy wyżej, w Javie można napisać też to co ty napisałeś w Pythonie, korzystając z bardzo podobnej składni.

0

@Shalom
Skoro "próba wskoczenia w języki trochę niższego poziomu jest bolesna", to jak powinienem podejść do tematu? Jak wymazać sobie z głowy dwa lata nauki?

0

Nic nie wymazuj tylko najpierw naucz się porządnie chociażby funkcjonalności istniejących w bibliotece standardowej Javy, bo zamiast z niej korzystać wymyślasz koło od nowa. Tak się nie robi, bo im więcej natrzaskasz własnego bezsensownego kodu tym większa szansa, że gdzieś wkradnie się błąd (albo wiele błędów).

1 użytkowników online, w tym zalogowanych: 0, gości: 1