Avatar billede starfish Nybegynder
28. november 2001 - 15:14 Der er 7 kommentarer og
1 løsning

Valg af datastruktur (ArrayList, HashMap, etc.)

Hejsa.

Jeg er i gang med et skoleprojekt hvor jeg skal lave et kundekartotek. Dette kartotek skal indeholde kunder og der skal kunne søges i dem på følgende måder:

Søgning på navn (delvis match)
- resulterer i at alle elementer skal løbes igennem.
- kan ikek finde på en datastruktur der er at foretræke her.

Søgning på Telefon nr. (100% match)
- HashMap er vel det mest optimale?
Søgning på Kunde nr. (100% match)
- HashMap er vel det mest optimale?

Ligeledes skal det være muligt at komme fra en kunde til en anden ved at trykke på en \"Forrige\" eller \"Næste\" knap.

Dette betyder at en indekseret Collection ville være at foretrække (f.eks. LinkedList, ArrayList...)

Der skal kunne indsættes/slettes kunder hvilket peger på LinkedList mht. hastighed.

Det betyder at jeg har lidt svært ved at bestemme mig.

Alternativt kunne jeg have en linkedList til at sætte ind i/slette fra / kalde forrige/næste fra og så opretholde en hashMap for både telefonnr. søgning og kundenr. søgning.

Er jeg helt på afveje?

Nogle forslag til hvad jeg kan gøre? Evt noget helt andet end det jeg har gang i. Konkret kode er ikkw at foretrække da det som skrevet er et skoleprojekt og jeg ved at en færdig løsning vil med min dovenskab resultere i at jeg intet lærer :-)

Gode idéer / forslag ønskes.
Avatar billede ricki Nybegynder
28. november 2001 - 15:33 #1
Hvis rækkefølgen er vigtig så er det korrekt at du skal have fat i fx LinkedList eller ArrayList. Hvilken du skal vælge af disse kommer så an på hvor ofte du vil indsætte og fjerne noder - hvis det vil ske ofte vil LinkedList være at foretrække da den som navnet siger er implementeret som en hægtetliste, hvorimod ArrayList er implementeret med et array hvor noderne så skal flyttes når du fjerner en, og når arrayet er fyldt så skal de alle overføres til et nyt array (alt sammen noget man ikke behøver tænke på, men en tanke der er god at tage med når man vælger den ene frem for den anden)

Dit problem med søgning er måske lidt overkill at have to ekstra datastrukturere at vedligeholde. En måde du kunne gøre det på var ved at lave to Comparator\'e (en til kundenr og en til telefon), og så benytte den indbyggede binær søgefunktion som du finde java.util.Collections - den der se sådan her ud:
binarySearch(List list, Object key, Comparator c)
Avatar billede erikjacobsen Ekspert
28. november 2001 - 16:36 #2
Jeg vil ikke anbefale en binær søgning - og så kan spørgeren jo tænke
lidt over hvorfor....
Avatar billede starfish Nybegynder
28. november 2001 - 17:34 #3
Hej Erik, du har jo nok gættet at jeg går i din javawww klasse :-)

Tænker...

Umiddelbart kan jeg se at binær søgning er et problem hvis jeg f.eks. vælger at sortere mit array efter navn eller andet der ikke er et tal? (1)

Hvis vi går ud fra at jeg sorterer mine kunder efter navn får jeg ikke andet ud af det end at det bliver vist i en logisk (alfabetisk) rækkefølge for brugeren. Så hastighedsmæssigt vinder jeg intet da en evt. søgning jo alligevel skal ALLE kunder igennem for at finde dem der matcher.

Hvis jeg går ud fra at kundernummer og telefonnummer begger er unikke så var det jo en mulighed at lave de to HashMaps HMTelefon og HMKundeNummer og så referere til det samme Kunde objekt?

Sådan et HashMap kan jeg vel bare køre en \"values\" på og på det resultat kan jeg lave en \"sort\" (på navn)?

Jeg antager at der vil foretages flest tilgange af objekter. Er det helt hen i skoven?


--
1:
Det er år og dag siden jeg sidst har brugt binær søgning så jeg kan godt være helt galt på den her :-)



Avatar billede erikjacobsen Ekspert
28. november 2001 - 18:39 #4
Jeg skulle nok præcisere, at du ikke kan bruge binær søgning på både kundenummer
og telefon, da den kun kan være sorteret efter ét kriterie.

I den første implementation kunne du også vælge almindelig lineær søgning.
Avatar billede logical Nybegynder
30. november 2001 - 10:34 #5
Jeg ville gøre som du foreslår, nemlig at bruge flere collections til at indeholde de samme data. Det er ikke noget problem, fordi de altid referer til de samme objekter:

Eksempelvis:

private Map telefonnøgle = new HashMap();
private Map kundenøgle = new HashMap();
private Map namenøgle = new HashMap();
private List originalorder = new ArrayList();;

public void add(Kunde k) {
  telefonnøgle.put(k.getTelefonnummer(), k);
  kundenøgle.put(k.getKundenummer(), k);
  namenøgle.put(k.getNavn(), k);
  originalorder.add(k);
  // Der er kun referencer i de enkelte collections, og derfor kan det sagtens addes til flere.
}


public Kunde findKundePåTelefonnummer(String tlfnr) {
  return telefonnøgle.get(tlfnr);
}
public Kunde findKundePåKundenummer(String knr) {
  return kundenøgle.get(knr);
}

public Kunde findKundePåNavn(String navn) {
  return namenøgle.get(navn);
}

Med hensyn til at kigge på dem, vil jeg anbefale en ListIterator (har next/prev og remove funktioner indbygget). Man skal dog passe på at fjerne ting fra en collection, som man er igang med at traversere via en iterator. Det skal helst ske fra iteratoren. Sagt med andre ord, har du en normal remove metode, der fjerner fra alle collections, vil en ListIterator kaste en ConcurrentModificationException hvis det sker undervejs, hvis du derimod kalder remove på din iterator får du ikke slette fra dine Maps.
Et alternativ med WeakHashMap er ikke muligt (umiddelbart) hvis man bruger Strings eller Wrapper klasser (som Integer).

Derfor skriv en decorator til din listiterator, ala:
private class MyListIterator implements ListIterator {
  private ListIterator inner;
  private Object current = null;
  public MyListIterator(ListIterator li) {
  this.inner = li;
  }

  public boolean hasNext() {
  return inner.hasNext();
  }
  public boolean hasPrev() {
  return inner.hasPrev();
  }
  public Object next() {
    current = inner.next();
    return current;
  }
  public Object prev() {
  current = inner.prev();
  return current;
  }
  ... // Fortsæt med de andre metoder undtagen remove.
  public void remove() {
    Kunde k = (Kunde) current;
    inner.remove();
    telefonnøgle.remove(k.getTelefonnummer());
    kundenøgle.remove(k.getKundenummer());
    namenøgle.remove(k.getNavn());
  }
}

// Og så returner sådan en i din klasse:
public ListIterator getListIterator() {
  return new MyListIterator(originalOrder.listIterator());
}


Med hensyn til valg af ArrayList/LinkedList, så afprøv scenariet med nogle realistiske testscenarier, og vælg den som performer bedst :-)
Det kaldes deterministisk modellering, og bør altid afprøves.
Avatar billede starfish Nybegynder
30. november 2001 - 12:16 #6
Det lyder helt fornuftigt det du skriver der logical. Med hensyn til LinkedList kan jeg ikke umiddelbart se at der er next() og prev() metoder. Ligeledes kan jeg ikke finde Iterators hasPrev() og Prev() metoder. Jeg kigger i min bog \"Java in a nutshel\" hvor de står beskrevet men åbentbart ikke godt nok?
Avatar billede logical Nybegynder
30. november 2001 - 12:42 #7
Kig i List interfacet, de har en metode:
public ListIterator listIterator();

Ligesom Collection har public Iterator iterator();

I modsætning til Iterator fra Collection kan ListIterator nemlig gå både forlæns (hasNext() og next()) og baglæns (hasPrev() og prev())
Avatar billede starfish Nybegynder
30. november 2001 - 13:41 #8
Nåja, det kan jeg godt se nu jeg kigger efter. tak for det... :-)

det er åbentbart ikke nok at have bogen, man skal sørme også kunne finde ud af at slå op i den.. LOL


Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester