|
|
- # Yhteystiedot ja osoitekirja 3/3 - Yhteystietojen järjestäminen aakkosjärjestykseen
-
- Tässä tehtävässä sinun tehtäväsi on järjestää yhteystiedot nimien mukaiseen aakkosjärjestykseen. Tämä tehtävä on ohjelmointi 1 -kurssin näkökulmasta edistynyttä lisäsisältöä, minkä vuoksi se on julkaistu bonustehtävänä.
-
- ## Taustatietoa
-
- Jos yritämme järjestää oman Contact-luokan oliot Collections.sort-metodin avulla, saamme seuraavan virheilmoituksen:
-
- ```
- "The method sort(List) in the type Collections is not applicable for the arguments (List)"
- ```
-
- Tämä johtuu siitä, että luokkamme ei ole yhteensopiva `Comparable`-tyypin kanssa. `Collections.sort`-metodi ei siis pysty vertailemaan olioitamme keskenään ilman, että määrittelemme sille lisäksi käytettävän vertailuoperaation.
-
- Tutustu Javan `Comparator.comparing`-metodiin, jonka avulla voit määritellä vertailijan kutsumaan mitä tahansa oman luokkasi metodia olioiden järjestämiseksi: [https://www.baeldung.com/java-8-comparator-comparing](https://www.baeldung.com/java-8-comparator-comparing). Tällä kurssilla sinun kannattaa lukea artikkelista kohta [3.1. Key Selector Variant](https://www.baeldung.com/java-8-comparator-comparing#1-key-selector-variant) ja sitä aikaisemmat kappaleet, mutta ei välttämättä tätä kappaletta pidemmälle.
-
- Kuten artikkelissa kerrotaan, `Comparator.comparing`-metodille voidaan antaa metodiviittaus mihin tahansa metodiin. `Collections.sort` käyttää tällöin vertailussa juuri haluamasi metodin palauttamia arvoja, joita vertaillaan keskenään. Voisimme siis esimerkiksi järjestää merkkijonot pituusjärjestykseen vertailemalla merkkijonojen pituuksia, jotka selviävät `length()`-metodin avulla: `Comparator.comparing(String::length)`.
-
- `Collections.sort` käyttää tässä esimerkissä järjestelemiseen `Comparator`-oliota, joka vertaa merkkijonojen pituuksia toisiinsa:
-
- ```
- List nesteet = Arrays.asList("maito", "Vesi", "ketsuppi", "bensa", "Limu");
- // tehdään järjestely merkkijonojen length-metodin mukaan:
- Collections.sort(nesteet, Comparator.comparing(String::length));
-
- System.out.println(nesteet); // lyhimmästä merkkijonosta pisimpään: [Limu, Vesi, bensa, maito, ketsuppi]
- ```
-
- ## Tehtävä
-
- Jatkokehitä nyt edellisissä tehtävissä käyttämiäsi kolmea osoitekirja- ja yhteystietoluokkaa siten, että osoitekirjan sisältöä listattaessa "list"-komennolla yhteystiedot esitetään aakkosjärjestyksessä nimen mukaan.
-
- Sinun kannattaa hyödyntää edellä käsiteltyä `Collections.sort`-metodia sekä `Comparator.comparing`-metodia siten, että annat comparing-metodille metodiviittauksen `Contact`-luokkasi `getName`-metodiin.
-
- ## ESIMERKKI
-
- ```
- This is an address book application. Available commands:
- list
- help
- add <name>, <email>, <phone>
- search <name>
- exit
-
- > add Maija Meikäläinen, maija@example.com, +35850555556
- Added Maija Meikäläinen (email: maija@example.com, phone: +35850555556)
-
- > add Matti Meikäläinen, matti@example.com, +35850555555
- Added Matti Meikäläinen (email: matti@example.com, phone: +35850555555)
-
- > add Benjamin Meikäläinen, benjamin@example.com, +35850555557
- Added Benjamin Meikäläinen (email: benjamin@example.com, phone: +35850555557)
-
- > add Abraham Meikäläinen, abraham@example.com, +35850555558
- Added Abraham Meikäläinen (email: abraham@example.com, phone: +35850555558)
-
- > add Wolverine Meikäläinen, wolverine@example.com, +35850555559
- Added Wolverine Meikäläinen (email: wolverine@example.com, phone: +35850555559)
-
- > list
- Abraham Meikäläinen (email: abraham@example.com, phone: +35850555558)
- Benjamin Meikäläinen (email: benjamin@example.com, phone: +35850555557)
- Maija Meikäläinen (email: maija@example.com, phone: +35850555556)
- Matti Meikäläinen (email: matti@example.com, phone: +35850555555)
- Wolverine Meikäläinen (email: wolverine@example.com, phone: +35850555559)
-
- > exit
- Bye!
- ```
-
- **AddressBookApp.java**
-
- ```
- import java.util.ArrayList;
- import java.util.List;
- import java.util.Scanner;
-
- public class AddressBookApp {
-
- private static String welcomeText = "This is an address book application. Available commands:\n";
- private static String commandMenu = " list\n" +
- " help\n" +
- " add <name>, <email>, <phone>\n" +
- " search <name>\n" +
- " exit\n";
-
- // Keep here instead of translating to a local variable
- private static String inputCLIPrefix = "> ";
-
- // Keep added addressBook values during application runtime
- private static AddressBook addressBook = new AddressBook();
-
- public static void main(String[] args) {
-
- System.out.print(welcomeText + commandMenu);
-
- while (true) {
- runApp();
- }
- }
-
- private static void runApp() {
-
- Scanner inputPrompt = new Scanner(System.in);
- Object[] getInput = parseInput(inputCLIPrefix, inputPrompt);
-
- String inputCmd = String.valueOf(getInput[0]);
-
- // TODO Avoid risk of ClassCastException
- List<String> inputArgs = (ArrayList<String>)getInput[1];
- int argsCount = 3;
-
- switch(inputCmd) {
- case "list":
- System.out.println(addressBook.toString());
- break;
- case "help":
- System.out.print(welcomeText + commandMenu);
- break;
- case "add":
-
- // TODO Should this be checked in AddressBook.add method instead?
- if (inputArgs.size() != argsCount) {
- System.err.printf("Invalid count of input arguments (expected %d).\n", argsCount);
- break;
- }
-
- String name = String.valueOf(inputArgs.get(0));
- String email = String.valueOf(inputArgs.get(1));
- String phone = String.valueOf(inputArgs.get(2));
-
- Contact contact = new Contact(name, email, phone);
-
- // NOTE: Else condition not needed as 3 arguments is always passed to this object method call
- if(addressBook.add(contact)) {
- System.out.printf("Added %s\n", contact.toString());
- }
-
- break;
- case "search":
-
- String searchTerm = String.valueOf(inputArgs.get(0));
- Contact match = addressBook.search(searchTerm);
-
- if (match == null) {
- System.out.printf("%s does not match any contact.\n", searchTerm);
- } else {
- System.out.println(match.toString());
- }
-
- break;
- case "exit":
- System.out.print("Bye!\n");
- System.exit(0);
- default:
- System.err.println("Command not found.");
- //break;
- }
- }
-
- private static Object[] parseInput(String prefix, Scanner inputRaw) {
-
- System.out.print(prefix);
- String inputR = inputRaw.nextLine();
-
- String command = inputR.split(" ")[0];
-
- String[] theRest = inputR.split(",");
- theRest[0] = theRest[0].replaceAll("^\\s*" + command + "\\s*","");
- List<String> arguments = new ArrayList<String>();
- for (int i = 0; i < theRest.length; i++) {
- arguments.add(theRest[i].trim());
- }
-
- Object[] parsedOutput = new Object[2];
- parsedOutput[0] = command;
- parsedOutput[1] = arguments;
-
- return parsedOutput;
- }
-
- }
- ```
-
- **AddressBook.java**
-
- ```
- import java.util.ArrayList;
- import java.util.Collections;
- import java.util.Comparator;
- import java.util.List;
-
- public class AddressBook {
-
- private List<Contact> contacts;
-
- public AddressBook() {
- this.contacts = new ArrayList<>();
- }
-
- public boolean add(Contact newContact) {
-
- // Create a temporary ArrayList, if we have contacts already
- // Get list of all contacts, put them into the new ArrayList contactsTemp
- // Loop through all contacts in contactsTemp
- // Check the current contact in contactsTemp against newContact
- if (this.contacts.size() > 0) {
- List<Contact> contactsTemp = new ArrayList<>(this.contacts);
-
- for (Contact tempContact : contactsTemp) {
- if (tempContact.equals(newContact)) {
- System.out.println("That contact already exists.");
- return false;
- }
- }
-
- }
-
- this.contacts.add(newContact);
- return true;
- }
-
- public Contact search(String keyword) {
- for (Contact current : this.contacts) {
- String name = current.getName();
- if (name != null && name.toLowerCase().contains(keyword.toLowerCase())) {
- return current; // palautetaan löytynyt arvo heti
- }
- }
- return null; // palautetaan null, jos ei löytynyt
- }
-
- @Override
- public String toString() {
- String returnString = "";
-
- // Sort by contact names. Define new Comparator object
- Collections.sort(this.contacts, new Comparator<Contact>() {
- public int compare(Contact contact1, Contact contact2) {
- return contact1.getName().compareTo(contact2.getName());
- }
- });
-
- for (Contact contact : this.contacts) {
- returnString += contact + "\n";
- }
- return returnString;
- }
- }
- ```
-
- **Contact.java**
-
- ```
- public class Contact {
-
- private String name;
- private String email;
- private String phone;
-
- // NOTE: This does not validate or check input String values
- // (Is name actually a name, email a valid email, and phone number an actual phone number?)
- public Contact(String name, String email, String phone) {
- this.name = name;
- this.email = email;
- this.phone = phone;
- }
-
- public String getName() {
- return this.name;
- }
-
- @Override
- public boolean equals(Object contact) {
-
- if (this == contact) { return true; }
- if (!(this instanceof Contact)) { return false; }
-
- Contact contactT = (Contact) contact;
-
- if (this.name.equals(contactT.name) && this.email.equals(contactT.email) && this.phone.equals(contactT.phone)) {
- return true;
- }
-
- return false;
-
- }
-
- public String toString() {
- // Haluttu muoto: "Maija Meikäläinen (email: foo@bar.fi, phone: 5555)"
- return this.name + " (email: " + this.email + ", phone: " + this.phone + ")";
- }
- }
- ```
|