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..a9cfe5f8508a07b201ea75d595556d7628c9cbc4 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; @@ -35,5 +35,28 @@ public class Kirja { this.julkaisuVuosi = julkaisuVuosi; } + @Override + public Kirja clone() + { + return new Kirja(kirjanNimi, kirjailijanNimi, julkaisuVuosi); + } + + @Override + public String toString() + { + return kirjanNimi + ", " + kirjailijanNimi + ", " + julkaisuVuosi; + } + @Override + public boolean equals(Object obj) + { + if (obj == null) return false; + if (obj == this) return true; + if (!(obj instanceof Kirja)) return false; + + Kirja toinen = (Kirja)obj; + return toinen.kirjanNimi.equals(kirjanNimi) && + toinen.kirjailijanNimi.equals(kirjailijanNimi) && + toinen.julkaisuVuosi == julkaisuVuosi; + } } 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..5f681f3f836a8b992d31c1410e9d428e5ef4e3f8 100644 --- a/src/main/java/fi/utu/tech/ooj/exercise3/KirjaKokoelma.java +++ b/src/main/java/fi/utu/tech/ooj/exercise3/KirjaKokoelma.java @@ -4,7 +4,7 @@ import java.io.PrintStream; import java.util.ArrayList; import java.util.List; -public class KirjaKokoelma { +public class KirjaKokoelma implements Cloneable{ private String kokoelmanNimi; private ArrayList<Kirja>kirjaListaus; @@ -30,4 +30,56 @@ public class KirjaKokoelma { kirjaListaus.add(teos); } + @Override + public KirjaKokoelma clone() + { + KirjaKokoelma kopio = new KirjaKokoelma(kokoelmanNimi); + for (Kirja kirja : kirjaListaus) + { + kopio.lisaaKirja(kirja); + } + return kopio; + } + + @Override + public String toString() + { + StringBuilder palautus = new StringBuilder(); + palautus.append(kokoelmanNimi).append("\n"); + for (Kirja kirja : kirjaListaus) + { + palautus.append(kirja.toString()).append("\n"); + } + return palautus.toString(); + } + + @Override + public boolean equals(Object obj) + { + if (obj == null) return false; + if (obj == this) return true; + if (!(obj instanceof KirjaKokoelma)) return false; + + KirjaKokoelma toinen = (KirjaKokoelma)obj; + + if (!(toinen.kokoelmanNimi.equals(kokoelmanNimi)) || + toinen.kirjaListaus.size() != kirjaListaus.size()) return false; + + for (Kirja kirja : toinen.kirjaListaus) + { + boolean on = false; + for (Kirja kirja1 : kirjaListaus) + { + if (kirja1.equals(kirja)) { + on = true; + break; + } + } + if (!on) + { + return false; + } + } + return true; + } } 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..018abe04894aeea6b4997fea4a1c72f1e8b3400a 100644 --- a/src/main/java/fi/utu/tech/ooj/exercise3/Kirjasto.java +++ b/src/main/java/fi/utu/tech/ooj/exercise3/Kirjasto.java @@ -5,7 +5,7 @@ import java.util.HashSet; import java.util.List; import java.util.Set; -public class Kirjasto { +public class Kirjasto implements Cloneable { private String kirjastonNimi; private String osoite; @@ -57,5 +57,85 @@ public class Kirjasto { sivukirjastot.add(input); } + @Override + public Kirjasto clone() + { + Kirjasto kopio = new Kirjasto(kirjastonNimi, osoite); + for (KirjaKokoelma kokoelma : kokoelmat) + { + kopio.lisaaKokoelma(kokoelma.clone()); + } + for (Kirjasto kirjasto : sivukirjastot) + { + kopio.lisaaSivukirjasto(kirjasto.clone()); + } + return kopio; + } + + @Override + public String toString() + { + StringBuilder palautus = new StringBuilder(); + palautus.append(kirjastonNimi).append("\n"); + palautus.append(osoite).append("\n"); + palautus.append("Kokoelmat:").append("\n"); + for (KirjaKokoelma kokoelma : kokoelmat) + { + palautus.append(kokoelma.toString()).append("\n"); + } + palautus.append("Sivukirjastot:").append("\n\n"); + for (Kirjasto kirjasto : sivukirjastot) + { + palautus.append(kirjasto.toString()); + } + return palautus.toString(); + } + @Override + public boolean equals(Object obj) + { + if (obj == null) return false; + if (obj == this) return true; + if (!(obj instanceof Kirjasto)) return false; + + Kirjasto toinen = (Kirjasto)obj; + + if (!(toinen.kirjastonNimi.equals(kirjastonNimi) && + toinen.osoite.equals(osoite))) return false; + + if (toinen.kokoelmat.size() != kokoelmat.size()) return false; + for (KirjaKokoelma kokoelma : toinen.kokoelmat) + { + boolean on = false; + for (KirjaKokoelma kokoelma1 : kokoelmat) + { + if (kokoelma1.equals(kokoelma)) { + on = true; + break; + } + } + if (!on) + { + return false; + } + } + + if (toinen.sivukirjastot.size() != sivukirjastot.size()) return false; + for (Kirjasto kirjasto : toinen.sivukirjastot) + { + boolean on = false; + for (Kirjasto kirjasto1 : sivukirjastot) + { + if (kirjasto1.equals(kirjasto)) { + on = true; + break; + } + } + if (!on) + { + return false; + } + } + return true; + } } 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..f5aec7c321494cda42135cbf959921407f0332dc 100644 --- a/src/main/java/fi/utu/tech/ooj/exercise3/Main.java +++ b/src/main/java/fi/utu/tech/ooj/exercise3/Main.java @@ -14,7 +14,7 @@ public class Main { */ - public static void main(String[] args) { + public static void main(String[] args){ /* * Testin jälkeen alla olevan rivin voi joko kommentoida tai poistaa. */ @@ -24,5 +24,84 @@ public class Main { HashSet<HenkiloAuto> henkiloautot = new HashSet<HenkiloAuto>(); HashSet<KuormaAuto> kuormaautot = new HashSet<KuormaAuto>(); + + // ---Tehtävä 2 demonstrointi--- + System.out.println("---Tehtävä 2---"); + Kirjasto kirjasto = new Kirjasto("Turku", "Linnankatu"); + //sivukirjastot + Kirjasto kirjasto1 = new Kirjasto("Feeniks", "Yliopisto"); + Kirjasto kirjasto2 = new Kirjasto("Nummi", "Halistentie"); + //kokoelmat + KirjaKokoelma[] kokoelmat = { + new KirjaKokoelma("fantasia"), + new KirjaKokoelma("scifi"), + new KirjaKokoelma("kauhu"), + new KirjaKokoelma("draama"), + new KirjaKokoelma("trilleri"), + new KirjaKokoelma("rikos") + }; + //lisätään kirjat kokoelmiin + int indeksi = 1; + for (KirjaKokoelma kokoelma : kokoelmat) + { + for (int i = 0; i < 2; i++) { + kokoelma.lisaaKirja(new Kirja( + "Kirja" + indeksi, + "Kirjailija" + indeksi, + indeksi)); + indeksi++; + } + } + // kokoelmat kirjastoihin + kirjasto.lisaaKokoelma(kokoelmat[0]); + kirjasto.lisaaKokoelma(kokoelmat[1]); + kirjasto1.lisaaKokoelma(kokoelmat[2]); + kirjasto1.lisaaKokoelma(kokoelmat[3]); + kirjasto2.lisaaKokoelma(kokoelmat[4]); + kirjasto2.lisaaKokoelma(kokoelmat[5]); + //kirjastot sivukirjastoiksi + kirjasto.lisaaSivukirjasto(kirjasto1); + kirjasto.lisaaSivukirjasto(kirjasto2); + + System.out.println(kirjasto.toString()); + + Kirjasto kopio = kirjasto.clone(); + System.out.println(kirjasto.equals(kopio)); + + + // ---tehtävä 3 demonstrointi--- + System.out.println("---Tehtävä 3---"); + HashMap<String, String> map = new HashMap<>(); + map.put("Hei", "Heippa"); + map.put("Moi", "Moikka"); + RandomMap rmap = new RandomMap<>(map); + System.out.println(rmap.get("Hei")); + System.out.println(rmap.get("terve") + "\n"); // Heippa tai Moikka + + + // ---tehtävä 4 demonstrointi--- + System.out.println("---Tehtävä 4---"); + Triplet<String, Integer, Double> triplet = new Triplet<>(); + triplet.put("avain1", 1, 1.11); + triplet.put("avain2", 2, 2.22); + triplet.put("avain3", 3, 3.33); + + System.out.println(triplet.getFirstValue("avain1")); + System.out.println(triplet.getSecondValue("avain3") + "\n"); + + System.out.println(triplet.keySet()); + System.out.println(triplet.firstValues()); + System.out.println(triplet.secondValues() + "\n"); + + System.out.println(triplet.containsKey("avain2")); // true + System.out.println(triplet.containsKey("avain4")); // false + System.out.println(triplet.containsValue(1, 1.11)); // true + System.out.println(triplet.containsValue(4, 4.44) + "\n"); // false + + System.out.println(triplet.isEmpty()); // false + System.out.println(triplet.size()); + triplet.remove("avain3"); + triplet.clear(); + System.out.println(triplet.isEmpty()); // true } } 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..ee9681dcc150a5de3cec3e13615a09e736c72814 --- /dev/null +++ b/src/main/java/fi/utu/tech/ooj/exercise3/RandomMap.java @@ -0,0 +1,75 @@ +package fi.utu.tech.ooj.exercise3; + +import java.util.*; + +public class RandomMap <T extends Map> implements Map{ + + T map; + + public RandomMap(T map) + { + this.map = map; + } + @Override + public int size() { + return map.size(); + } + + @Override + public boolean isEmpty() { + return map.isEmpty(); + } + + @Override + public boolean containsKey(Object o) { + return map.containsKey(o); + } + + @Override + public boolean containsValue(Object o) { + return map.containsValue(o); + } + + @Override + public Object get(Object o) { + if (map.get(o) != null) return map.get(o); + ArrayList<Object> arvot = new ArrayList<Object>(map.values()); + Collections.shuffle(arvot); + return arvot.get(0); + } + + @Override + public Object put(Object o, Object o2) { + return map.put(o, o2); + } + + @Override + public Object remove(Object o) { + return map.remove(o); + } + + @Override + public void putAll(Map map1) { + map.putAll(map1); + } + + @Override + public void clear() { + map.clear(); + } + + @Override + public Set keySet() { + return map.keySet(); + } + + @Override + public Collection values() { + return map.values(); + } + + @Override + public Set<Entry> entrySet() { + return map.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..d76c989151de5721b32991951a478c33c2eb59cc --- /dev/null +++ b/src/main/java/fi/utu/tech/ooj/exercise3/Triplet.java @@ -0,0 +1,90 @@ +package fi.utu.tech.ooj.exercise3; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; + +public class Triplet <K, V, W> implements TripletMap<K, V, W>{ + + private HashMap<K, Object[]> map; + + public Triplet() + { + map = new HashMap<>(); + } + + @Override + public void put(K key, V value1, W value2) { + map.put(key, new Object[]{value1, value2}); + } + + @Override + public V getFirstValue(K key) { + return (V)map.get(key)[0]; + } + + @Override + public W getSecondValue(K key) { + return (W)map.get(key)[1]; + } + + @Override + public void remove(K key) { + map.remove(key); + } + + @Override + public void clear() { + map.clear(); + } + + @Override + public Set<K> keySet() { + return map.keySet(); + } + + @Override + public Set<V> firstValues() { + Set<V> fValues = new HashSet<>(); + for (Object[] pari : map.values()) + { + fValues.add((V)pari[0]); + } + return fValues; + } + + @Override + public Set<W> secondValues() { + Set<W> sValues = new HashSet<>(); + for (Object[] pari : map.values()) + { + sValues.add((W)pari[1]); + } + return sValues; + } + + @Override + public boolean containsKey(Object key) { + return map.containsKey(key); + } + + @Override + public boolean containsValue(Object value1, Object value2) { + for (Object[] pari : map.values()) + { + if (pari[0].equals(value1) && pari[1].equals(value2)) return true; + } + return false; + } + + @Override + public boolean isEmpty() { + return map.isEmpty(); + } + + @Override + public int size() { + return map.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..63a9e2578de39207a849ba9a1b967899f6beeeab --- /dev/null +++ b/src/main/java/fi/utu/tech/ooj/exercise3/TripletMap.java @@ -0,0 +1,21 @@ +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(); + +} diff --git a/src/main/java/fi/utu/tech/ooj/exercise3/tehtava1 b/src/main/java/fi/utu/tech/ooj/exercise3/tehtava1 new file mode 100644 index 0000000000000000000000000000000000000000..13b9a330f6361e78d0ac09e092470c4579bd783d --- /dev/null +++ b/src/main/java/fi/utu/tech/ooj/exercise3/tehtava1 @@ -0,0 +1,54 @@ +Tehtävä 1 + + +A. Collection ja Map + +Collection ja Map ovat rajapinta-luokkia. Collection-luokkaan pohjautuvat tietorakenteet +ovat homogeenisiä, kun taas Map-luokka rakentuu avain-arvo-pareista, eli tietoa voi etsiä +avaimen perusteella, eivätkä alkiot ole missään tietyssä järjestyksessä. +Map-luokkien vahvuus on nopea tiedonhaku avaimen perusteella, eli jokaista alkiota ei +tarvitse käydä erikseen läpi. Sama avain voi esiintyä vain kerran, mutta arvo voi olla +sama kuin jokin toinen arvo. +Collection-luokkaa voidaan käyttää kun halutaan ryhmä objekteja, johon voi listätä, poistaa +ja hakea jäseniä. Mahdollisia ominaisuuksia ovat, että objektit pysyvät samassa järjestyksessä +ja duplikaatteja ei sallita + + +B. List, Set ja Queue + +Kaikki kolme kokoelmatyyppiä pohjautuu Collection-luokkaan. List-tyyppi tarjoaa dynaamisen +indeksoidun tietorakenteen, johon voi lisätä, hakea ja poistaa alkioita vapaasti. +List säilyttää oletuksena lisäysjärjestyksen, mutta alkioita voi poistaa tai lisätä sen +keskelle. List sallii myös duplikaatit. +Set-tyyppinen kokoelma on joukko uniikkeja objekteja, eli se ei salli duplikaatteja. +Set tarjoaa myös lisäämis, poistamis ja haku operaatiot, mutta ei säilytä objekteja +tietyssä järjestyksessä. +Queue toimii nimen mukaisesti jonona, eli käyttäytyy first-in-first-out periaatteella. +Objektit ovat lisäysjärjestyksessä ja uusi objekti lisätään aina jonon perälle, ja jonosta +voi poistaa vanhimman eli jonon ensimmäisen objektin. Queue-luokka sopii tilanteeseen, missä +tarvitaan järjestynyt jono, jota voidaan hallita. + + +C. ArrayList ja LinkedList + +ArrayList toteuttaa List-luokan, eli se on dynaaminen ja indeksoitu taulukkolista. +Se tarjoaa objektien lisäämisen ja poiston, sekä haun indeksin perusteella. +LinkedList pohjautuu List- ja Queue-luokkiin. Se on linkitetty lista, eli jokaisella alkiolla +tai "solmulla" on tieto omasta arvosta ja viittaus seuraavaan solmuun. Listaan voi lisätä ja +siitä voi poistaa, sekä alusta, että lopusta. Listan keskeltä voi poistaa solmun, mutta +indeksin perusteella poistaminen on hidasta, koska lista on käytävä läpi alusta. +ArrayList sopii tilanteisiin, joissa tarvitaan tehokkaita hakutoimintoja ja sopii satunnaisiin +lisäyksiin ja poistoihin, mutta varaa myös enemmän muistia. +LinkedList sopii tilanteeseen, jossa satunnaista hakua ei tarvi, vaan tehokas poisto tai lisäys +listan alusta tai lopusta. + + +D. HashSet ja TreeSet + +HashSet ja TreeSet toteuttavat Set-rajapinnan. HashSet perustuu hajautustauluun ja tarjoaa +nopeat yleiset operaatiot. Se ei säilytä määriteltyä järjestystä. +TreeSet tallentaa objektit puuhun ja säilyttää järjestyksen. Lisäys, haku ja poisto toimivat +hitaammin kuin HashSetissä, koska tiedon hallinta vaatii puun rakentamista ja järjestyksen +ylläpitämistä. TreeSetin vahvuudet ovat siis tilanteessa, missä tarvitaan järjestettyjä +operaatioita esim. pienimmästä suurimpaan. HashSet on hyvä tilanteessa, missä tiedonhaun +ja tallentamisen tehokkuus on tärkeintä. \ No newline at end of file diff --git a/src/main/java/fi/utu/tech/ooj/exercise3/tehtava5 b/src/main/java/fi/utu/tech/ooj/exercise3/tehtava5 new file mode 100644 index 0000000000000000000000000000000000000000..93e2a96b6f64fb75baa087846dab4d1177e72327 --- /dev/null +++ b/src/main/java/fi/utu/tech/ooj/exercise3/tehtava5 @@ -0,0 +1,23 @@ +Tehtävä 5 + + +A. + +Signatuuri <X extends Z, Y extends Z, Z extends Ajoneuvo> tarkoittaa, että alatyypit X ja Y +periytyvät luokasta Z, joka periytyy luokasta Ajoneuvo. Tällöin siis xs kokoelma sisältää +Z-tyyppisiä elementtejä tai sen alatyyppiä X. ys sisältää Z tyyppiä tai alatyyppiä Y. +Rutiini palauttaa listan Z-tyyppisenä eli se on yhteensopiva Ajoneuvo-luokan perivien +luokkien kanssa, jotka ovat yliluokkia tyypeille Y ja X. + + +B. + +Onnistuu, koska kummatkin luokat perivät saman luokan eli Ajoneuvon. Jos lista sisältää +yläluokan olioita, sen perivät luokat voidaan lisätä siihen. Viittausta henkilö- ja +kuormaautot listoihin ei voi sijoittaa, koska listojen sisältämein olioiden tyyppi on +erilainen. +Tilanne voidaan korjata vapaalla tyypillä: + +HashSet<Ajoneuvo> ajoneuvot = new HashSet<Ajoneuvo>(); +HashSet<? extends HenkiloAuto> henkiloautot = new HashSet<>(); +HashSet<? extends KuormaAuto> kuormaautot = new HashSet<>(); \ No newline at end of file