This shows you the differences between two versions of the page.
|
poo-ca-cd:laboratoare:colectii-tipuri-de-date-speciale-si-utilitare [2025/11/10 00:46] florian_luis.micu [For-each] |
poo-ca-cd:laboratoare:colectii-tipuri-de-date-speciale-si-utilitare [2025/11/17 02:11] (current) florian_luis.micu [Obiective] |
||
|---|---|---|---|
| Line 9: | Line 9: | ||
| Pe parcursul laboratoarelor și temelor ați folosit structuri de date oferite de API-ul Java. În cadrul acestui laborator le vom aprofunda. | Pe parcursul laboratoarelor și temelor ați folosit structuri de date oferite de API-ul Java. În cadrul acestui laborator le vom aprofunda. | ||
| - | * lucrul cu cele trei tipuri principale de colecții din Java: List, Set, Map | + | |
| - | * cunoașterea diferențelor dintre implementările colecțiilor (eficiență, sortare, ordonare etc) | + | Aspectele urmărite sunt: |
| - | * compararea elementelor unor colecții | + | * tipuri Wrapper peste primitive. |
| - | * contractul equals-hashcode | + | * lucrul cu cele trei tipuri principale de colecții din Java: List, Set, Queue, Map. |
| + | * cunoașterea diferențelor dintre implementările colecțiilor (eficiență, sortare, ordonare etc). | ||
| + | * compararea elementelor unor colecții. | ||
| + | * contractul equals-hashCode. | ||
| + | Aspectele **bonus** urmărite sunt: | ||
| + | * utilitare din biblioteca Math. | ||
| + | * lucrul cu date și ore. | ||
| + | * folosirea tipurilor BigInteger și BigDecimal. | ||
| + | |||
| + | <note warning> | ||
| + | * În acest laborator există mai multe secțiuni marcate **[Optional]**. Aceste secțiuni cuprind informații **bonus** care vă pot fi prezentate în **timpul laboratorului** sau pe care le puteți aprofunda **în afara** acestuia, ele nefiind necesare pentru laboratoarele viitoare sau pentru teme. | ||
| + | * De asemenea, veți întâlni câteva secțiuni marcate **[Nice to know]**. Vă recomandăm ca acestea să aibă **prioritate** în parcurgerea secțiunilor de tip **[Optional]**, deoarece vă pot oferi informații bonus care să fie și foarte probabil utile pentru **teme** sau **laboratoare viitoare**. | ||
| + | </note> | ||
| =====🌯 Wrappers pentru tipuri primitive===== | =====🌯 Wrappers pentru tipuri primitive===== | ||
| Line 32: | Line 44: | ||
| ====Clase Wrapper==== | ====Clase Wrapper==== | ||
| - | Pentru a permite utilizarea valorilor primitive în contexte ce necesită obiecte (de exemplu, în colecții despre care vom vorbi în următoarele laboratore), Java oferă clase wrapper **dedicate** fiecărui tip primitiv. | + | Pentru a permite utilizarea valorilor primitive în contexte ce necesită obiecte (de exemplu, în colecții despre care vom vorbi mai jos), Java oferă clase wrapper **dedicate** fiecărui tip primitiv. |
| ^Tip primitiv^Clasă wrapper corespunzătoare^ | ^Tip primitiv^Clasă wrapper corespunzătoare^ | ||
| Line 46: | Line 58: | ||
| <note tip> | <note tip> | ||
| - | Wrapper-ele tipurilor primitive sunt **immutable**. Vom afla în următoarele laboratoare mai multe despre acest concept. | + | Wrapper-ele tipurilor primitive sunt **immutable**. |
| </note> | </note> | ||
| Line 274: | Line 286: | ||
| Vom învăța mai multe despre acesta în laboratorul despre **genericitate**. | Vom învăța mai multe despre acesta în laboratorul despre **genericitate**. | ||
| + | </note> | ||
| + | |||
| + | <note tip> | ||
| + | Pe parcursul laboratorului veți vedea notații de tipul ''<E>'', ''<T>'', ''<K, V>''. Vom înțelege în următoarele laboratoare la ce se referă exact, însă pentru acest laborator este suficient să știți că sunt niște **notații** pentru a semnala că o colecție folosește un **tip omogen** (ex. ''Collection<E>'' -> ''Collection'' poate folosi doar un tip omogen denumit ''E'' care poate fi un obiect). | ||
| </note> | </note> | ||
| Line 751: | Line 767: | ||
| </note> | </note> | ||
| + | =====🧮 [Nice to know] Math Utilities===== | ||
| + | |||
| + | Java oferă suport nativ pentru **operații aritmetice pe tipuri primitive** (''int'', ''long'', ''float'', ''double''). Pentru operații mai complexe, cum ar fi funcții trigonometrice, radăcini pătrate sau generarea de numere aleatoare, clasa ''java.lang.Math'' oferă **metode statice** gata de folosit. Aceasta nu poate fi instanțiată, **fiind un utilitar de tip static**. | ||
| + | |||
| + | Pentru aritmetica întregilor, împărțirea la zero aruncă o excepție de tip ''ArithmeticException''. În schimb, operațiile pe numere zecimale (''double''/''float'') nu aruncă excepții, ci pot returna valori speciale precum ''POSITIVE_INFINITY'', ''NEGATIVE_INFINITY'' sau ''NaN''. | ||
| + | |||
| + | Tabelul de mai jos sintetizează principalele metode din clasa ''Math'': | ||
| + | |||
| + | <spoiler Tabel metode clasa Math> | ||
| + | ^ Metodă ^ Tip argument ^ Funcționalitate ^ Exemplu ^ | ||
| + | | ''Math.abs(a)'' | int, long, float, double | Valoarea absolută | ''Math.abs(-5)'' → 5 | | ||
| + | | ''Math.max(a,b)'' | int, long, float, double | Max dintre două valori | ''Math.max(3,7)'' → 7 | | ||
| + | | ''Math.min(a,b)'' | int, long, float, double | Min dintre două valori | ''Math.min(3,7)'' → 3 | | ||
| + | | ''Math.pow(a,b)'' | double | a ridicat la puterea b | ''Math.pow(2,3)'' → 8.0 | | ||
| + | | ''Math.sqrt(a)'' | double | Rădăcină pătrată | ''Math.sqrt(16)'' → 4.0 | | ||
| + | | ''Math.round(a)'' | float/double | Rotunjire la întreg | ''Math.round(1.7)'' → 2 | | ||
| + | | ''Math.ceil(a)'' | double | Rotunjire în sus | ''Math.ceil(1.3)'' → 2.0 | | ||
| + | | ''Math.floor(a)'' | double | Rotunjire în jos | ''Math.floor(1.7)'' → 1.0 | | ||
| + | | ''Math.sin(a)'' / ''Math.cos(a)'' / ''Math.tan(a)'' | double | Funcții trigonometrice | ''Math.sin(Math.PI/2)'' → 1.0 | | ||
| + | | ''Math.random()'' | – | Generare număr aleator [0,1) | ''Math.random()'' → 0.374 | | ||
| + | | ''Math.toDegrees(a)'' / ''Math.toRadians(a)'' | double | Conversie radian ↔ grade | ''Math.toDegrees(Math.PI)'' → 180.0 | | ||
| + | </spoiler> | ||
| + | |||
| + | <html><br></html> | ||
| + | |||
| + | =====🐋 [Optional] BigInteger și BigDecimal===== | ||
| + | |||
| + | Tipurile primitive ''long'' și ''double'' au limite în ceea ce privește dimensiunea și precizia. Dacă ai nevoie de numere foarte mari sau de zecimale cu precizie arbitrară, poți folosi clasele ''BigInteger'' și ''BigDecimal'' din pachetul ''java.math''. | ||
| + | * ''BigInteger'' permite operații aritmetice pe numere întregi de orice dimensiune, fără să apară overflow. | ||
| + | * ''BigDecimal'' permite operații pe numere zecimale cu precizie controlată și este ideal pentru calcule financiare sau științifice. | ||
| - | ====Iteratori==== | ||
| - | Un iterator este un obiect care permite traversarea unei colecţii şi modificarea acesteia (ex: ştergere de elemente) în mod selectiv. Puteţi obţine un iterator pentru o colecţie, apelând metoda sa **iterator()**. Interfaţa [[https://docs.oracle.com/javase/8/docs/api/java/util/Iterator.html|Iterator]] este următoarea: | ||
| <code java> | <code java> | ||
| - | public interface Iterator<E> { | + | BigInteger b1 = new BigInteger("9223372036854775807"); |
| - | boolean hasNext(); | + | BigInteger b2 = new BigInteger("2"); |
| - | E next(); | + | System.out.println(b1.add(b2)); // 9223372036854775809 |
| - | void remove(); // optional | + | |
| - | } | + | BigDecimal bd1 = new BigDecimal("1.0"); |
| + | BigDecimal bd2 = new BigDecimal("3"); | ||
| + | BigDecimal result = bd1.divide(bd2, 100, BigDecimal.ROUND_UP); | ||
| + | System.out.println(result); // 0.3333...3334 (100 cifre) | ||
| </code> | </code> | ||
| - | Exemplu de folosire a unui iterator: | + | Aceste clase oferă metode pentru adunare, scădere, înmulțire, împărțire și control precis al rotunjirii. |
| + | |||
| + | <note tip> | ||
| + | Nu există o limită bine definită pentru BigInteger sau BigDecimal, puteți stoca **orice număr** atâta timp cât există memorie RAM disponibilă. | ||
| + | </note> | ||
| + | |||
| + | =====🕒 [Nice to know] Lucrul cu date și ore===== | ||
| + | |||
| + | Java include mai multe clase pentru manipularea timpului și a datelor: | ||
| + | * ''java.time.LocalDate'' – reprezintă doar data, fără timp. | ||
| + | * ''java.time.LocalTime'' – reprezintă doar timpul, fără dată. | ||
| + | * ''java.time.LocalDateTime'' – combină data și ora. | ||
| + | * ''java.time.ZonedDateTime'' – reprezintă un moment exact într-un fus orar, luând în calcul ajustările de vară. | ||
| + | |||
| + | Crearea instanțelor se poate face fie cu valorile numerice folosind ''of()'', fie prin parsarea stringurilor folosind ''parse()''. De asemenea, metoda ''now()'' returnează momentul curent. | ||
| + | |||
| + | ====LocalDate==== | ||
| + | |||
| + | Reprezintă o **dată fără timp** (ex: 2023-03-31). Ideal pentru evenimente sau zile calendaristice. | ||
| + | |||
| + | Puteți crea un obiect folosind metoda ''now()'' pentru data curentă sau ''of()'' pentru o dată specifică. | ||
| + | |||
| + | ^ Metodă ^ Funcționalitate ^ Exemplu ^ | ||
| + | | ''LocalDate.now()'' | Data curentă | ''LocalDate today = LocalDate.now();'' | | ||
| + | | ''LocalDate.of(year, month, day)'' | Creează o dată specifică | ''LocalDate piDay = LocalDate.of(2023, 3, 14);'' | | ||
| + | | ''LocalDate.parse(String, DateTimeFormatter)'' | Parsează un string | ''LocalDate valentine = LocalDate.parse("02/14/23", shortUS);'' | | ||
| + | | ''plus()'' / ''minus()'' | Adaugă sau scade unități de timp | ''today.plus(1, ChronoUnit.WEEKS);'' | | ||
| <code java> | <code java> | ||
| - | Collection<Double> col = new ArrayList<Double>(); | + | LocalDate today = LocalDate.now(); |
| - | Iterator<Double> it = col.iterator(); | + | LocalDate reminder = today.plus(1, ChronoUnit.WEEKS); |
| + | System.out.println(reminder); // o săptămână de la azi | ||
| + | </code> | ||
| - | while (it.hasNext()) { | + | ====LocalTime==== |
| - | Double backup = it.next(); | + | |
| - | // apelul it.next() trebuie realizat înainte de apelul it.remove() | + | Reprezintă o **oră fără dată** (ex: 07:15). Util pentru alarme sau ore de evenimente recurente. |
| - | if (backup < 5.0) { | + | |
| - | it.remove(); | + | ^ Metodă ^ Funcționalitate ^ Exemplu ^ |
| - | } | + | | ''LocalTime.now()'' | Ora curentă | ''LocalTime now = LocalTime.now();'' | |
| - | } | + | | ''LocalTime.of(hour, minute)'' | Creează o oră specifică | ''LocalTime alarm = LocalTime.of(7, 15);'' | |
| + | | ''parse(String, DateTimeFormatter)'' | Parsează un string | ''LocalTime sunset = LocalTime.parse("2020", military);'' | | ||
| + | |||
| + | <code java> | ||
| + | LocalTime alarm = LocalTime.of(7, 15); | ||
| + | System.out.println(alarm); // 07:15 | ||
| </code> | </code> | ||
| - | Apelul metodei [[http://docs.oracle.com/javase/7/docs/api/java/util/Iterator.html#remove()|remove()]] a unui iterator face posibilă eliminarea elementului din colecţie care a fost întors la ultimul apel al metodei **next()** din acelaşi iterator. | + | ====LocalDateTime==== |
| - | În exemplul anterior, toate elementele din colecţie mai mici decât 5 for fi şterse la ieşirea din bucla ''while''. | + | |
| + | Reprezintă **data și timpul împreună**, fără fus orar. Este util pentru programări și timestamp-uri locale. | ||
| + | |||
| + | ^ Metodă ^ Funcționalitate ^ Exemplu ^ | ||
| + | | ''LocalDateTime.now()'' | Data și ora curentă | ''LocalDateTime now = LocalDateTime.now();'' | | ||
| + | | ''LocalDateTime.of(year, month, day, hour, minute)'' | Creează un obiect specific | ''LocalDateTime appointment = LocalDateTime.of(2023,5,4,7,0);'' | | ||
| + | | ''plus()'' / ''minus()'' | Manipulare date și timp | ''appointment.plusDays(2);'' | | ||
| + | |||
| + | <code java> | ||
| + | LocalDateTime appointment = LocalDateTime.of(2023,5,4,7,0); | ||
| + | LocalDateTime nextAppointment = appointment.plusHours(3); | ||
| + | System.out.println(nextAppointment); // 2023-05-04T10:00 | ||
| + | </code> | ||
| + | |||
| + | ====ZonedDateTime==== | ||
| + | |||
| + | Reprezintă un **moment exact într-un fus orar**, incluzând ajustările de vară. Este esențial când aplicația se folosește în mai multe zone. | ||
| + | |||
| + | ^ Metodă ^ Funcționalitate ^ Exemplu ^ | ||
| + | | ''ZonedDateTime.now()'' | Data și ora curentă cu fus orar | ''ZonedDateTime now = ZonedDateTime.now();'' | | ||
| + | | ''atZone(ZoneId)'' | Atașează un fus orar la LocalDateTime | ''ZonedDateTime ny = appointment.atZone(ZoneId.of("America/New_York"));'' | | ||
| + | | ''withZoneSameInstant(ZoneId)'' | Convertire instantanee într-un alt fus | ''ZonedDateTime paris = ny.withZoneSameInstant(ZoneId.of("Europe/Paris"));'' | | ||
| + | |||
| + | <code java> | ||
| + | LocalDateTime piLocal = LocalDateTime.parse("2023-03-14T01:59"); | ||
| + | ZonedDateTime piCentral = piLocal.atZone(ZoneId.of("America/Chicago")); | ||
| + | ZonedDateTime piParis = piCentral.withZoneSameInstant(ZoneId.of("Europe/Paris")); | ||
| + | System.out.println(piParis); // 2023-03-14T07:59+01:00[Europe/Paris] | ||
| + | </code> | ||
| + | |||
| + | ====DateTimeFormatter și formatarea datelor și orelor==== | ||
| + | |||
| + | Permite **formatări și parsări personalizate** pentru date și timp. Aceleași formate pot fi folosite și pentru parsarea string-urilor. | ||
| + | |||
| + | ^ Caracteristică ^ Funcționalitate ^ Exemplu ^ | ||
| + | | ''ofPattern(String)'' | Creează un format personalizat | ''DateTimeFormatter shortUS = DateTimeFormatter.ofPattern("MM/dd/yy");'' | | ||
| + | | ''format(TemporalAccessor)'' | Formatează o dată sau oră | ''shortUS.format(today);'' | | ||
| + | | ''parse(String)'' | Parsează un string conform formatului | ''LocalDate valentine = LocalDate.parse("02/14/23", shortUS);'' | | ||
| + | |||
| + | <code java> | ||
| + | DateTimeFormatter military = DateTimeFormatter.ofPattern("HHmm"); | ||
| + | LocalTime sunset = LocalTime.parse("2020", military); | ||
| + | System.out.println(sunset); // 20:20 | ||
| + | |||
| + | DateTimeFormatter appointment = DateTimeFormatter.ofPattern("h:mm a MM/dd/yy z"); | ||
| + | ZonedDateTime dentist = ZonedDateTime.parse("10:30 AM 11/01/23 EST", appointment); | ||
| + | System.out.println(dentist); // 2023-11-01T10:30-04:00[America/New_York] | ||
| + | |||
| + | LocalTime t = LocalTime.now(); | ||
| + | System.out.println(withSeconds.format(t)); // ex: 09:17:34 | ||
| + | System.out.println(military.format(t)); // ex: 0917 | ||
| + | </code> | ||
| + | |||
| + | Puteți crea formate foarte variate pentru afișări personalizate folosind caracterele din ''DateTimeFormatter''. | ||
| + | |||
| + | <spoiler Tabel de formatare> | ||
| + | ^ Caracter ^ Descriere ^ Exemplu ^ | ||
| + | | a | AM/PM | PM | | ||
| + | | d | Ziua din lună | 10 | | ||
| + | | E | Ziua din săptămână | Tue, Tuesday | | ||
| + | | G | Era | BCE, CE | | ||
| + | | k | Ora (1-24) | 24 | | ||
| + | | K | Ora AM/PM (0-11) | 0 | | ||
| + | | L | Luna din an | Jul, July | | ||
| + | | h | Ora AM/PM (1-12) | 12 | | ||
| + | | H | Ora din zi (0-23) | 0 | | ||
| + | | m | Minute | 30 | | ||
| + | | M | Luna din an (numeric) | 7, 07 | | ||
| + | | s | Secunde | 55 | | ||
| + | | S | Fracțiune de secundă | 033954 | | ||
| + | | u | An (fără era) | 2004, 04 | | ||
| + | | y | An cu era | 2004, 04 | | ||
| + | | z | Numele fusului orar | Pacific Standard Time, PST | | ||
| + | | Z | Offset fus orar | +0000, -0800, -08:00 | | ||
| + | </spoiler> | ||
| + | |||
| + | ====Timestamps==== | ||
| + | |||
| + | Clasele ''Instant'' și ''ChronoUnit'' permit manipularea timestamp-urilor precise, ideale pentru logging sau urmărirea evenimentelor: | ||
| + | |||
| + | <code java> | ||
| + | Instant time1 = Instant.now(); | ||
| + | Instant time2 = Instant.now(); | ||
| + | |||
| + | System.out.println(time1.isAfter(time2)); // false | ||
| + | System.out.println(time1.plus(3, ChronoUnit.DAYS)); // 3 zile mai târziu | ||
| + | </code> | ||
| + | |||
| + | ''Instant'' este similar cu clasa veche ''Date'', dar mult mai consistent și integrat cu ''java.time''. | ||
| + | |||
| + | ====Recomandări==== | ||
| + | |||
| + | * Folosiți **LocalDate** pentru date fără timp și **LocalTime** pentru timp fără dată. | ||
| + | * **LocalDateTime** combină data și ora, dar nu include fusul orar. | ||
| + | * **ZonedDateTime** este necesar când lucrați cu aplicații globale și fusuri orare. | ||
| + | * **DateTimeFormatter** permite formatarea și parsarea flexibilă a datelor și orelor. | ||
| + | * **Instant** reprezintă un timestamp precis pentru evenimente și log-uri. | ||
| + | |||
| + | <note tip> | ||
| + | Puteți să consultați pachetele ''java.util'', ''java.text'' și ''java.time'' pentru mai multe utilitare care vă pot fi de folos. De exemplu, vă puteți uita la ''java.util.Random'' pentru generarea de numere aleatoare. | ||
| + | </note> | ||
| + | |||
| =====Summary===== | =====Summary===== | ||
| Line 791: | Line 974: | ||
| =====Exerciţii===== | =====Exerciţii===== | ||
| + | |||
| + | ====Task 1 (10p)==== | ||
| + | |||
| 1. În cadrul acestui exercițiu, veți implementa o clasă numită Student, care are patru membri: | 1. În cadrul acestui exercițiu, veți implementa o clasă numită Student, care are patru membri: | ||
| - name (String) | - name (String) | ||
| Line 804: | Line 990: | ||
| 4. Extindeți clasa LinkedHashSet<Integer> cu o clasă în care se vor putea adăuga doar numere pare. Metoda add va fi suprascrisă astfel încât să nu permită adăugarea de numere impare în colecție. Efectuați aceeași operațiune și pentru clasele TreeSet și HashSet. Observați diferențele privind ordinea de inserare a elementelor între cele trei clase menționate. | 4. Extindeți clasa LinkedHashSet<Integer> cu o clasă în care se vor putea adăuga doar numere pare. Metoda add va fi suprascrisă astfel încât să nu permită adăugarea de numere impare în colecție. Efectuați aceeași operațiune și pentru clasele TreeSet și HashSet. Observați diferențele privind ordinea de inserare a elementelor între cele trei clase menționate. | ||
| - | |||
| - | Scheletul il puteți gasi pe [[https://github.com/oop-pub/oop-labs/blob/master/src/lab8/Main.java|github]]. Soluția trebuie încărcată pe [[https://code.devmind.ro|devmind]]. | ||
| =====Resurse și Linkuri utile===== | =====Resurse și Linkuri utile===== | ||
| * [[https://www.tutorialspoint.com/java/java_collections.htm|Java Collections - Tutorial Point]] | * [[https://www.tutorialspoint.com/java/java_collections.htm|Java Collections - Tutorial Point]] | ||
| + | * [[https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html|Java Math]] | ||
| + | * [[https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/math/BigInteger.html|Java BigInteger]] | ||
| + | * [[https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/math/BigDecimal.html|Java BigDecimal]] | ||
| + | * [[https://www.baeldung.com/java-8-date-time-intro|Date and Time API - Baeldung]] | ||