Skip to content
Snippets Groups Projects
Commit b23f5da2 authored by Oiva Mickelsson's avatar Oiva Mickelsson
Browse files

toteutettiin tehtävät

parent 8a8bc36d
Branches master
No related tags found
No related merge requests found
Pipeline #64048 passed
......@@ -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);
......
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;
}
......
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;
......
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;
}
......
......@@ -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);
}
}
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();
}
}
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;
}
}
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);
}
}
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
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment