diff --git a/src/main/java/fi/utu/tech/ooj/exercise3/Ajoneuvo.java b/src/main/java/fi/utu/tech/ooj/exercise3/Ajoneuvo.java index 7eaa5d5ac226a452d030d2eabf191911e7637d7e..3798d77db2ef4cfdf6479e54cb2e73d898ed71f6 100644 --- a/src/main/java/fi/utu/tech/ooj/exercise3/Ajoneuvo.java +++ b/src/main/java/fi/utu/tech/ooj/exercise3/Ajoneuvo.java @@ -29,7 +29,10 @@ abstract class Ajoneuvo { public void setOmistaja(String omistaja) { this.omistaja = omistaja; } - +//Tässä esimerkissä Z sallii vain ajoneuvo-tyyppisiä tyyppiparametreja. X ja Y tyyppiparametrit sallivat, että +//tyypit voivat myös olla ajoneuvon alityyppejä. Eli X:n ja Y:n on oltava Z:an eli AjoNeuvon alityyppejä, jotta +//listojen yhdistäminen voisi olla mahdollista. Listaan tällöin on mahdollista ainoastaan lisätä tyyppejä, jotka +//ovat, joko samat kuin X ja Y tai X:n ja Y:n perijät. public static <X extends Z, Y extends Z, Z extends Ajoneuvo> Set<Z> yhdista(Set<X> xs, Set<Y> ys){ var tmp = new TreeSet<Z>(); for (var x : xs) tmp.add(x); diff --git a/src/main/java/fi/utu/tech/ooj/exercise3/Kirja.java b/src/main/java/fi/utu/tech/ooj/exercise3/Kirja.java index 13d735cebecb2492da4cdc2f967aed46ea347313..ab7e98e133ea3e9913df8e696c6e64a26baf17ae 100644 --- a/src/main/java/fi/utu/tech/ooj/exercise3/Kirja.java +++ b/src/main/java/fi/utu/tech/ooj/exercise3/Kirja.java @@ -1,6 +1,6 @@ package fi.utu.tech.ooj.exercise3; -public class Kirja { +public class Kirja implements Cloneable { private String kirjanNimi; private String kirjailijanNimi; private int julkaisuVuosi; @@ -10,7 +10,29 @@ public class Kirja { this.kirjailijanNimi = kirjailijanNimi; this.julkaisuVuosi = julkaisuVuosi; } - + @Override + public Kirja clone() throws CloneNotSupportedException { + //Tähän riittää pintakopio + return (Kirja)super.clone(); + } + @Override + public String toString() { + return "kirjanNimi: " + getKirjanNimi() + " kirjalijanNimi: " + getKirjailijanNimi() + " julkaisuVuosi: " + getJulkaisuVuosi() + " "; + } + @Override + public boolean equals(Object toinen) { + if (toinen == null) { + return false; + } + if (toinen == this) { + return true; + } + if (!(toinen instanceof Kirja)) { //toinen.getClass() != getClass() + return false; + } + Kirja k = (Kirja)toinen; + return k.kirjanNimi.equals(kirjanNimi) && k.kirjailijanNimi.equals(kirjailijanNimi) && k.julkaisuVuosi == julkaisuVuosi; + } public String getKirjanNimi() { return kirjanNimi; } diff --git a/src/main/java/fi/utu/tech/ooj/exercise3/KirjaKokoelma.java b/src/main/java/fi/utu/tech/ooj/exercise3/KirjaKokoelma.java index 285fd40c2145f3fa3ce10f18412afb657fe48f5e..9f0051c49c7d0fc5bf7022239a68bcaf770280a1 100644 --- a/src/main/java/fi/utu/tech/ooj/exercise3/KirjaKokoelma.java +++ b/src/main/java/fi/utu/tech/ooj/exercise3/KirjaKokoelma.java @@ -1,10 +1,13 @@ package fi.utu.tech.ooj.exercise3; import java.io.PrintStream; +import java.lang.reflect.Array; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.List; -public class KirjaKokoelma { +public class KirjaKokoelma implements Cloneable { private String kokoelmanNimi; private ArrayList<Kirja>kirjaListaus; @@ -13,6 +16,49 @@ public class KirjaKokoelma { this.kokoelmanNimi = kokoelmanNimi; this.kirjaListaus = new ArrayList<>(); } + @Override + public KirjaKokoelma clone() throws CloneNotSupportedException { + KirjaKokoelma k = (KirjaKokoelma)super.clone(); + k.kirjaListaus = new ArrayList<>(); + for (Kirja kirja : kirjaListaus) { + //Voimme nyt kloonata Kirja-tyyppisiä olioita, koska se ei enää ole suojattu package suojausmäärellä. + k.kirjaListaus.add((Kirja)kirja.clone()); + } + return k; + } + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("["); + for (Kirja k : getKirjaListaus()) { + sb.append(k.toString()); + } + sb.append("]"); + return "\nkokoelmanNimi: " + getkokoelmanNimi() + "\nkirjaListaus: " + sb; + } + @Override + public boolean equals(Object toinen) { + if (toinen == null) { + return false; + } + if (toinen == this) { + return true; + } + if (!(toinen instanceof KirjaKokoelma)) { //toinen.getClass() != getClass() + return false; + }//Kloonataan kirjakokoelmat, jotta rutiini toimisi sivuvaikutuksettomasti + KirjaKokoelma k = null; + KirjaKokoelma t = null; + try { + k = ((KirjaKokoelma)toinen).clone(); + t = ((KirjaKokoelma)this).clone(); + } catch (CloneNotSupportedException e) { + return false; + } + Collections.sort(k.getKirjaListaus(), Comparator.comparingInt(Kirja::getJulkaisuVuosi)); + Collections.sort(t.getKirjaListaus(), Comparator.comparingInt(Kirja::getJulkaisuVuosi)); + return k.getkokoelmanNimi().equals(kokoelmanNimi) && t.getKirjaListaus().equals(k.getKirjaListaus()); + } public String getkokoelmanNimi() { return kokoelmanNimi; diff --git a/src/main/java/fi/utu/tech/ooj/exercise3/Kirjasto.java b/src/main/java/fi/utu/tech/ooj/exercise3/Kirjasto.java index 2478ff6351648daef8b963f175230b13d1aa3569..ed0ee4bd0a6e2861a6aeddd604b412343baf9228 100644 --- a/src/main/java/fi/utu/tech/ooj/exercise3/Kirjasto.java +++ b/src/main/java/fi/utu/tech/ooj/exercise3/Kirjasto.java @@ -1,11 +1,8 @@ package fi.utu.tech.ooj.exercise3; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; -public class Kirjasto { +public class Kirjasto implements Cloneable { private String kirjastonNimi; private String osoite; @@ -16,12 +13,68 @@ public class Kirjasto { this.kirjastonNimi = kirjastonNimi; this.osoite = osoite; } + @Override + public Kirjasto clone() throws CloneNotSupportedException { + Kirjasto k = (Kirjasto)super.clone(); + k.kokoelmat = new ArrayList<>(); + for (KirjaKokoelma kokoelma : kokoelmat) { + k.kokoelmat.add((KirjaKokoelma)kokoelma.clone()); + } + k.sivukirjastot = new HashSet<>(); + for (Kirjasto sivukirjasto : sivukirjastot) { + k.sivukirjastot.add((Kirjasto)sivukirjasto.clone()); + } + return k; + } + @Override + public String toString() { + StringBuilder kokoelmat = new StringBuilder(); + kokoelmat.append(""); + for (KirjaKokoelma k : getKokoelmat()) { + kokoelmat.append(k.toString()); + } + kokoelmat.append(""); + StringBuilder sivukirjastot = new StringBuilder(); + for (Kirjasto ko : getSivukirjastot()) { + sivukirjastot.append(ko.toString()); // toteutetaan tämä rekursiivisesti + } + return "kirjastonNimi: " + getKirjastonNimi() + "\nosoite: " + getOsoite() + "\nkokoelmat: " + kokoelmat + + "\nsivuKirjastot: " + Arrays.toString(getSivukirjastot().stream().map(kirjasto -> kirjasto.getKirjastonNimi()).toArray(String[]::new)) + "\n" + sivukirjastot; + } + @Override + public boolean equals(Object toinen) { + if (toinen == null) { + return false; + } + if (toinen == this) { + return true; + } + if (!(toinen instanceof Kirjasto)) { //toinen.getClass() != getClass() + return false; + }//Kloonataan kirjastot, jotta rutiini toimisi sivuvaikutuksettomasti + Kirjasto k = null; + Kirjasto t = null; + try { + k = ((Kirjasto)toinen).clone(); + t = ((Kirjasto)this).clone(); + } catch (CloneNotSupportedException e) { + return false; + } + Collections.sort(k.getKokoelmat(), Comparator.comparing(KirjaKokoelma::getkokoelmanNimi)); + Collections.sort(t.getKokoelmat(), Comparator.comparing(KirjaKokoelma::getkokoelmanNimi)); + + for (Kirjasto kirjasto:t.getSivukirjastot()) { + if (!new ArrayList(List.of(k.getSivukirjastot().toArray())).contains(kirjasto)) { + return false; + } + } + return k.getKirjastonNimi().equals(t.getKirjastonNimi()) && k.getOsoite().equals(t.getOsoite()); + //&& k.getSivukirjastot().equals(t.getSivukirjastot()); + } public Set<Kirjasto> getSivukirjastot() { return sivukirjastot; } - - public String getKirjastonNimi() { return kirjastonNimi; } diff --git a/src/main/java/fi/utu/tech/ooj/exercise3/Main.java b/src/main/java/fi/utu/tech/ooj/exercise3/Main.java index 0c5fb2a608860ddf2225d92690eafd616fb4c96c..dd8ec7d3faeb16e96d8c14e07cbdf0cb62a09873 100644 --- a/src/main/java/fi/utu/tech/ooj/exercise3/Main.java +++ b/src/main/java/fi/utu/tech/ooj/exercise3/Main.java @@ -3,6 +3,8 @@ package fi.utu.tech.ooj.exercise3; import java.util.HashMap; import java.util.HashSet; +import java.util.List; +import java.util.Map; public class Main { @@ -19,10 +21,107 @@ public class Main { * Testin jälkeen alla olevan rivin voi joko kommentoida tai poistaa. */ System.out.println("*** Harjoitustyöpohja käynnistyy ***"); + Kirjasto turku = new Kirjasto("Turun pääkirjasto", "kirjatokatu 3"); + Kirjasto nummi = new Kirjasto("nummen kirjasto", "nummenkatu 1"); + Kirjasto itaharju = new Kirjasto("ita-harjun kirjasto", "itainen 7"); + turku.lisaaSivukirjasto(nummi); + turku.lisaaSivukirjasto(itaharju); - HashSet<Ajoneuvo> ajoneuvot = new HashSet<Ajoneuvo>(); - HashSet<HenkiloAuto> henkiloautot = new HashSet<HenkiloAuto>(); - HashSet<KuormaAuto> kuormaautot = new HashSet<KuormaAuto>(); + Kirja nainmuututmiljardooriksi = new Kirja("Näin muutut miljärdööriksi", "Pöhinä Petri", 2018); + Kirja universuminmysteetit = new Kirja("Universumin mysteerit", "Tiede Teppo", 2015); + KirjaKokoelma fakta = new KirjaKokoelma("Faktakirjallisuus"); + fakta.lisaaKirja(nainmuututmiljardooriksi); + fakta.lisaaKirja(universuminmysteetit); + + Kirja tahtientuhoja = new Kirja("Tähtien tuhoaja", "Luukas Yrjö", 1979); + Kirja robotittappaakaikki = new Kirja ("Robotit tappavat kaikki", "Pelkäävä Pentti", 2011); + KirjaKokoelma Scifi = new KirjaKokoelma("Sci-fi"); + Scifi.lisaaKirja(tahtientuhoja); + Scifi.lisaaKirja(robotittappaakaikki); + + Kirja fantastinenjuttu = new Kirja ("Fantastinen juttu", "Vitsaileva Viivi", 1996); + Kirja valtaistuinpeli = new Kirja ("Valtaistuinpeli", "Martti Yrjö", 1999); + KirjaKokoelma fantasia = new KirjaKokoelma("fantasia"); + fantasia.lisaaKirja(fantastinenjuttu); + fantasia.lisaaKirja(valtaistuinpeli); + + Kirja elamani = new Kirja("Elämäni", "Elävä Eeli", 2011); + Kirja menestys = new Kirja("Menestys", "Menestyvä Maija", 2012); + KirjaKokoelma elamankerrat = new KirjaKokoelma("Elämänkerrat"); + elamankerrat.lisaaKirja(elamani); + elamankerrat.lisaaKirja(menestys); + + Kirja meditointi = new Kirja("Meditointi", "Kultainen Markus", 100); + Kirja ajattelensiisolen = new Kirja("Ajattelen siis olen", "Tuhoisa Rene", 1600); + KirjaKokoelma filosofia = new KirjaKokoelma("Filosofia"); + filosofia.lisaaKirja(ajattelensiisolen); + filosofia.lisaaKirja(meditointi); + + Kirja jotainrunoja = new Kirja("Jotain runoja", "Runoileva Roni", 1999); + Kirja lisaaRunoja = new Kirja("Lisaa runoja", "Runoileva Roni", 2005); + KirjaKokoelma runollisuus = new KirjaKokoelma("Runollisuus"); + runollisuus.lisaaKirja(jotainrunoja); + runollisuus.lisaaKirja(lisaaRunoja); + + turku.lisaaKokoelma(fakta); + turku.lisaaKokoelma(Scifi); + nummi.lisaaKokoelma(fantasia); + nummi.lisaaKokoelma(runollisuus); + itaharju.lisaaKokoelma(filosofia); + itaharju.lisaaKokoelma(elamankerrat); + + System.out.println(turku.toString()); + Kirjasto åbo = null; + try { + åbo = turku.clone(); + } catch (Exception e) {} + System.out.println(åbo.toString()); + System.out.println(turku.equals(åbo)); + + HashMap<String, Integer> kaarittava = new HashMap<>(); + kaarittava.put("esim1", 214134); + kaarittava.put("esimerkki2", 15); + kaarittava.put("esimerkillinen3", 346); + RandomMap<String, Integer> kaari = new RandomMap<>(kaarittava); + System.out.println(kaari.size()); + System.out.println(kaari.get("e")); + + Triplet<String, Integer, Integer> tripletti = new Triplet<>(); + tripletti.put("esim1", 0, 251); + tripletti.put("esimerkki2", 15, 34); + System.out.println(tripletti.size()); + System.out.println(tripletti.firstValues()); + System.out.println(tripletti.secondValues()); + System.out.println(tripletti.keySet()); + System.out.println(tripletti.containsValue(0, 251)); + System.out.println(tripletti.containsKey("esim1")); + System.out.println(tripletti.isEmpty()); + System.out.println(tripletti.getFirstValue("esimerkki2")); + System.out.println(tripletti.getSecondValue("esimerkki2")); + tripletti.remove("esimerkki2"); + System.out.println(tripletti.keySet()); + tripletti.clear(); + System.out.println(tripletti.keySet()); + + //Lisäys onnistuu, koska Liskovin korvausperiaatteen mukaan henkilöaudon ja kuormaaudon on käyttäytyvä, kuten + //ajoneuvo, jonka takia lisäyksen on oltava mahdollista. Iteratiivinen lisääminen addall metodilla on + //mahdollista + //HashSet<Ajoneuvo> ajoneuvot = new HashSet<Ajoneuvo>(); + //HashSet<KuormaAuto> kuormaautot = new HashSet<KuormaAuto>(); + //HashSet<HenkiloAuto> henkiloautot = new HashSet<HenkiloAuto>(); + //ajoneuvot.addAll(henkiloautot); + //ajoneuvot.addAll(kuormaautot); + //SEt ajoneuvot luokkaa ei ole kuitenkaan mahdollista korvata luokalla, jonka tyypiargumenttina on sen aliluokka + //sen takia, että Javassa tämä ominaisuus on toteutettu eri tavalla. Javassa on käytettävä vapaata tyyppiä, + //jotta tämä olisi mahdollista. Liskovin korvausperiaatteen mukaan kuitenkin tämän pitäisi normaalistikin + //olla mahdollista, ja se on toteutettu eri tavoilla muissa kielissä. Javassa kuitenkin geneerisyys on + //käyttäytyy aina invarianttisesti + HashSet<? extends Ajoneuvo> ajoneuvot = new HashSet<Ajoneuvo>(); // Tämä voidaan korjata näin + ajoneuvot = new HashSet<HenkiloAuto>(); // jolloin tämä toimii + //Tämä toimii sen takia, että tyyppinä on vapaa tyyppi, joka seuraa liskovin korvausperiaatetta tarkemmin + + + System.out.println(ajoneuvot); } } diff --git a/src/main/java/fi/utu/tech/ooj/exercise3/RandomMap.java b/src/main/java/fi/utu/tech/ooj/exercise3/RandomMap.java new file mode 100644 index 0000000000000000000000000000000000000000..d2f8341864d286610949d78177feca31bf5cb246 --- /dev/null +++ b/src/main/java/fi/utu/tech/ooj/exercise3/RandomMap.java @@ -0,0 +1,89 @@ +package fi.utu.tech.ooj.exercise3; + +import java.util.*; +import java.util.function.BiConsumer; +import java.util.function.BiFunction; +import java.util.function.Function; + +public class RandomMap<K, V> implements Map<K, V> { + private Map<K, V> kaarittava; + + public RandomMap(Map<K, V> kaarittava) { + this.kaarittava = kaarittava; + } + @Override + public int size() { + return kaarittava.size(); + } + + @Override + public boolean isEmpty() { + return kaarittava.isEmpty(); + } + + @Override + public boolean containsKey(Object key) { + return kaarittava.containsKey(key); + } + + @Override + public boolean containsValue(Object value) { + return kaarittava.containsValue(value); + } + + @Override + public V get(Object key) { + Iterator<Entry<K,V>> i = kaarittava.entrySet().iterator(); + if (key==null) { + while (i.hasNext()) { + Entry<K,V> e = i.next(); + if (e.getKey()==null) + return e.getValue(); + } + } else { + while (i.hasNext()) { + Entry<K,V> e = i.next(); + if (key.equals(e.getKey())) + return e.getValue(); + } + } + List<V> a = new ArrayList<>(kaarittava.values().stream().toList()); + Collections.shuffle(a); + return a.get(0); + } + + @Override + public V put(K key, V value) { + return kaarittava.put(key, value); + } + + @Override + public V remove(Object key) { + return kaarittava.remove(key); + } + + @Override + public void putAll(Map<? extends K, ? extends V> m) { + kaarittava.putAll(m); + } + + @Override + public void clear() { + kaarittava.clear(); + } + + @Override + public Set<K> keySet() { + return kaarittava.keySet(); + } + + @Override + public Collection<V> values() { + return kaarittava.values(); + } + + @Override + public Set<Entry<K, V>> entrySet() { + return kaarittava.entrySet(); + } +} diff --git a/src/main/java/fi/utu/tech/ooj/exercise3/Triplet.java b/src/main/java/fi/utu/tech/ooj/exercise3/Triplet.java new file mode 100644 index 0000000000000000000000000000000000000000..b407e6450ef4a6653769a4ee04d487d0457619ec --- /dev/null +++ b/src/main/java/fi/utu/tech/ooj/exercise3/Triplet.java @@ -0,0 +1,169 @@ +package fi.utu.tech.ooj.exercise3; + +import java.lang.reflect.Array; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class Triplet<K, V, W> implements TripletMap<K, V, W> { + + private ArrayList<Entry<K, V, W>> table; + private Set<K> keys; + private Set<V> firstValues; + private Set<W> secondValues; + private int size; + + + static class Node<K, V, W> implements TripletMap.Entry<K, V, W> { + final K key; + V firstValue; + W secondValue; + + public Node(K key, V firstValue, W secondValue) { + this.key = key; + this.firstValue = firstValue; + this.secondValue = secondValue; + } + + @Override + public K getKey() { + return key; + } + + @Override + public V getFirstValue() { + return firstValue; + } + + @Override + public V setFirstValue(V firstValue) { + this.firstValue = firstValue; + return firstValue; + } + + @Override + public W getSecondValue() { + return secondValue; + } + + @Override + public W setSecondValue(W secondValue) { + this.secondValue = secondValue; + return secondValue; + } + } + + public Triplet() { + table = new ArrayList<Entry<K, V, W>>(); + keys = new HashSet<>(); + firstValues = new HashSet<>(); + secondValues = new HashSet<>(); + } + + @Override + public void put(K key, V value1, W value2) throws IllegalArgumentException { + if (! containsKey(key) || firstValues.contains(value1) || secondValues.contains(value2)) { + table.add(new Node<>(key, value1, value2)); + keys.add(key); + firstValues.add(value1); + secondValues.add(value2); + size++; + } else { + } + } + + @Override + public V getFirstValue(K key) { + int i = 0; + while (table.size() - i != 0) { + if (table.get(i).getKey().equals(key)) { + return table.get(i).getFirstValue(); + } else { + i++; + } + } + return null; + } + + @Override + public W getSecondValue(K key) { + int i = 0; + while (table.size() - i != 0) { + if (table.get(i).getKey().equals(key)) { + return table.get(i).getSecondValue(); + } else { + i++; + } + } + return null; + } + + @Override + public void remove(K key) { + int i = 0; + while (table.size() - i != 0) { + if (table.get(i).getKey().equals(key)) { + table.remove(i); + keys.remove(key); + firstValues.remove(getFirstValue(key)); + secondValues.remove(getSecondValue(key)); + size--; + } else { + i++; + } + } + } + + @Override + public void clear() { + table.clear(); + keys.clear(); + firstValues.clear(); + secondValues.clear(); + size = 0; + } + + @Override + public Set<K> keySet() { + return keys; + } + + @Override + public Set<V> firstValues() { + return firstValues; + } + + @Override + public Set<W> secondValues() { + return secondValues; + } + + @Override + public boolean containsKey(Object key) { + return keySet().contains(key); + } + + @Override + public boolean containsValue(Object value1, Object value2) { + int i = 0; + while (table.size() - i != 0) { + if (table.get(i).getFirstValue().equals(value1) && table.get(i).getSecondValue().equals(value2)) { + return true; + } else { + i++; + } + } + return false; + } + + @Override + public boolean isEmpty() { + return table.isEmpty(); + } + + @Override + public int size() { + return size; + } +} diff --git a/src/main/java/fi/utu/tech/ooj/exercise3/TripletMap.java b/src/main/java/fi/utu/tech/ooj/exercise3/TripletMap.java new file mode 100644 index 0000000000000000000000000000000000000000..f8ab80753ff0090a24cc71ca11f8b51e5d777ff4 --- /dev/null +++ b/src/main/java/fi/utu/tech/ooj/exercise3/TripletMap.java @@ -0,0 +1,39 @@ +package fi.utu.tech.ooj.exercise3; + +import java.util.Set; + +public interface TripletMap<K, V, W> { + + void put(K key, V value1, W value2); + + V getFirstValue(K key); + + W getSecondValue(K key); + + void remove(K key); + + void clear(); + + + Set<K> keySet(); + + Set<V> firstValues(); + + Set<W> secondValues(); + + boolean containsKey(Object key); + + boolean containsValue(Object value1, Object value2); + + boolean isEmpty(); + + int size(); + //Luodaan yksittäisille arvoille oma luokka, jotta arvojen käsittely olisi yksinkertaisempaa + interface Entry<K, V, W> { + K getKey(); + V getFirstValue(); + W getSecondValue(); + V setFirstValue(V value); + W setSecondValue(W value); + } +} diff --git a/src/main/java/fi/utu/tech/ooj/exercise3/tehtava1.txt b/src/main/java/fi/utu/tech/ooj/exercise3/tehtava1.txt new file mode 100644 index 0000000000000000000000000000000000000000..c6549ce98f1dc68b639ea4d166896e902135f884 --- /dev/null +++ b/src/main/java/fi/utu/tech/ooj/exercise3/tehtava1.txt @@ -0,0 +1,30 @@ +a. Collection:ia voidaan ajatella olevan joukko arvoja. Map toisaalta on joukko avain-arvo pareja, jossa avain kertoo +arvon sijannin. Collection:in perijöitä ovat List, Set ja Queue. Listassa voi olla duplikaatti arvoja, mutta Set:issä +ei. Map:in avaimia voidaan tällöin ajatella olevan samankaltaisia kuin Set ja arvojen kuten List, koska Map:issä ei +voi olla kaksi saman nimistä avainta. Map:ia kannattaa käyttää, kun on hyödyllistä yhdistää tieto tiettyyn arvoon. Eikä +tieto ole dynaaminen, mikä voi sekoittaa Map:in toimintoa. Map:in läpi tällöin ei tarvitse iteroida ja tieto +voidaan löytää suoraan avaimella. Esimerkki tästä olisi opiskelijan etsintä opiskelijanumeroilla. +Collectionia toisaalta kannattaa käyttää, kun on sallittavaa iteroida sen läpi löytääkseen tietyn arvon. +b. +Set eroaa List:istä ja queue:stä siten, että set:issä järjestys ei ole yhtä oleellinen. Set:in kaikki arvot on oltava +erit, jotta tietorakenteesta voidaan löytää tieto. Set on tällöin tapa varmistaa, että joka ikinen arvo on eri. Se olisi +esimerkiksi hyvä tapa tarkastaa, että on onko henkiötunnus validi etsimällä sen tietokannasta. List on toisaalta +parempi rakenne, jos halutaan sallia duplikaatit ja järjestys. Esimerkiksi kirja-olioiden lajittelu kirjalijan nimen +mukaan. Queue on näistä ankarin, se vaatii, että alkioiden poisto ja lisäys tapahtuu vain tietyssä järjestyksessä. +Ei ole mahdollista poistaa jäsentä Queue:n keskeltä esimerkiksi. Queue:llä voidaan esimerkiksi mallintaa +TYS:in asuntojen odottajia prioriteettijonona. Nykyisen asunnon etäisyys Turusta tai vaihto-opiskelijaisuus vaikuttaisi +mahdollisuuteen saada asunto, jolloin odottaja voidaan poistaa listasta. +c. +LinkedList:in on tuplasti linkitetty lista, joka tarkoittaa, että alkioissa on tieto edeltävästä ja seuraavasta +alkioista. LinkedList ja ArrayList ovat mutatoituvia. LinkedList on kuitenkin nopeampi, kun vaaditaan paljon jäsenien +lisäystä ja poistoa. ArrayList on parempi, jos on tärkeää löytää tietty jäsen listasta. ArrayList on toteutettu +Array rakenteella. ArrayList on hyvä yleiskäyttöinen tietorakenne. Sitä voidaan käyttää, kun listasta halutaan tehdä +mutatoituva. Esimerkiksi ostoslista, jossa halutaan sallia duplikaatit ja mutatoitavuus. LinkedList kannattaa valita, +kun suoritusresurssit ovat vähäisiä, ja halutaan lisätä tietorakenne, joka jatkuvasti lisää ja poistaa alkoita. +Esimerkisi lista tietyn kryptovaluutan omistajista. +d. +HashSet:in ja TreeSet:in pääero on, että HashSet ei takaa järjestystä. Tämän lisäksi HashMap sallii Null-arvot. +HashSet:in perusoperaatiot ovat suoritusnopeudeltaan vakioita. TreeSet:in perusoperaatiot ovat toisaalta logaritmisia. +HashSet:iä kannattaa käyttää, kun järjestys on epäoleellinen. Esimerkiksi rutiini, joka tarkastaa onko +sähköpostiosoitetta tietorakenteessa. TreeSet on hyvä vaihtoehto, kun halutaan tietorakenteella olevan järjestys, mutta +silti ei sallita duplikaatteja. Esimerkiksi grafiiikkakorttien järjestäminen prosessointivoimansa mukaisesti. \ No newline at end of file