Hoofdstuk 20: JAVA UTILITIES PACKAGE EN BIT-MANIPULATIE 1 H 20. JAVA UTILITIES PACKAGE AND BIT-MANIPULATION 1. INLEIDING De package java.util bevat klassen om stacks, vectoren, hashtabellen en bitsets te verwerken. Hoewel deze klassen elk een specifieke functie hebben, bieden ze allemaal een mechanisme om gegevens op te slaan en op te halen. 2 H 20. JAVA UTILITIES PACKAGE EN BIT MANIPULATIE 1. INLEIDING In dit hoofstuk worden enkele klassen en een interface van package java.util besproken: klasse Vector interface Enumeration klasse Stack klasse Hashtable klasse Properties klasse BitSet 3 2. KLASSE Vector EN INTERFACE Enumeration Klasse java.util.Vector – Vector is een groeibare array. M.a.w. tijdens runtime kan de lengte van de array groter en kleiner worden. – Vector bevat een capaciteit • Capaciteit geeft het aantal objecten aan die een vector kan bevatten. M.a.w. het aantal objecten van een vector is steeds kleiner of gelijk aan de capaciteit. 4 2. KLASSE Vector: capaciteit Als de capaciteit overtroffen wordt, dan breidt ze zich automatisch uit, om de bijkomende gegevens te kunnen opvangen Ze breidt zich uit met de "capacity increment" capaciteit = capaciteit + "capacity increment" OF indien de "capacity increment" niet werd gedefinieert dan breidt ze zich uit met de "default capacity increment". De "default capacity increment" verdubbelt de 5 capaciteit. 2. KLASSE Vector: constructoren Er zijn vier constructoren voor de klasse Vector: vector1 = new Vector() Creëert een lege vector met capaciteit van 10 objecten en met de "default capacity increment" ("capacity increment" = 0). vector2 = new Vector(collection) Creëert een vector, gevuld met de objecten van de collection. De capaciteit is het aantal objecten die in de collection staan. De vector bevat de "default capacity increment". Collections wordt in het volgend hoofdstuk uitgelegd. 6 2. KLASSE Vector: constructoren vector3 = new Vector(lengte) Creëert een lege vector met capaciteit het aantal objecten dat door de integer "lengte" wordt aangegeven en met de "default capacity increment". vector4 = new Vector(lengte, toename) Idem als vector3, behalve met de "capacity increment" dat door de integer "toename" wordt aangegeven. 7 2. KLASSE Vector: methodes add en insertElementAt Methode add • add(object) "object" wordt op het einde van de Vector toegevoegd. • add(plaats, object) De objecten vanaf index "plaats" worden met één plaats opgeschoven. Vervolgens wordt "object" toegevoegd op index "plaats" in de Vector . Methode insertElementAt • insertElementAt(object, plaats) Idem als de methode add(plaats, object) 8 2. KLASSE Vector: methode add Vector vector = new Vector(); //capaciteit = 10 elementen vector.add( "magenta" ); magenta 0 1 2 ... 9 vector.add( "cyan" ); // "cyan" wordt op het einde van // de vector toegevoegd, dus op index 1 magenta 0 cyan 1 2 ... 9 try { vector.add( 1, "green" ); } //op index 1 wordt // "green" toegevoegd catch (ArrayIndexOutOfBoundsException exception) { exception.printStackTrace(); } magenta 0 green 1 cyan 2 3 ... 9 9 2. KLASSE Vector: methode get en type-casting Methode get • get(plaats) De referentie van het object op index "plaats" wordt teruggegeven. TYPE-CASTING • Alles wat we in een vector plaatsen, wordt eerst geconverteerd naar een object van klasse Object. Hieruit volgt dat we alles erin kunnen plaatsen wat we willen. Maar om er iets uit te krijgen, moeten we eerst weten waarnaar het moet worden gecast! 10 2. KLASSE Vector: methode get en type-casting Vector vector = new Vector(); String mijnString = "red"; JButton mijnButton = new JButton("kleur"); Integer mijnGetal = new Integer(5); vector.add(mijnString); vector.add(mijnButton); vector.add(mijnGetal); try { String nieuweString = (String) vector.get(0); JButton nieuweButton = (JButton) vector.get(1); Integer nieuwGetal = (Integer) vector.get(2); }//werpt een exception indien index < 0 of index >= size() catch (ArrayIndexOutOfBoundsException exception) { exception.printStackTrace(); } 11 2. KLASSE Vector: methodes set en setElementAt Methode set: • set(plaats, object) Op index "plaats" wordt het object gewijzigd door het "object". Het vorig object wordt teruggegeven. Methode setElementAt • setElementAt(object, plaats) Idem als de methode set(plaats, object), behalve dat deze methode niks teruggeeft (void). 12 2. KLASSE Vector: methodes set en setElementAt Vector vector = new Vector(); vector.add( "magenta" ); vector.add( "green" ); try { String color = (String) vector.set(1,"red"); System.out.println( "Het oorspronkelijk kleur was: " + color + "\n" ); vector.setElementAt("white",0); }//werpt een exception indien index<0 of index >= size() catch (ArrayIndexOutOfBoundsException exception) { exception.printStackTrace();} De vector bevat, na de set en setElementAt methodes, op index 0 het object "white" en op index 1 "red". Op het scherm wordt weergegeven: Het oorspronkelijke kleur was: green 13 2. KLASSE Vector: methodes firstElement en lastElement Methode firstElement Geeft de referentie van het eerste object van de Vector terug Methode lastElement Geeft de referentie van het laatste object van de Vector terug // het eerste en laatste element weergeven try { System.out.println( "First element: " + vector.firstElement() ); System.out.println( "Last element: " + vector.lastElement() ); } // catch exception indien de vector leeg is catch ( NoSuchElementException exception ) 14 { exception.printStackTrace(); } 2. KLASSE Vector: methode indexOf Methode indexOf • • indexOf(object) geeft de index terug waar het "object" het eerst in de Vector voorkomt. Indien het "object" niet voorkomt, dan geeft de methode –1 terug. indexOf(object,plaats) geeft de index terug waar het "object", vanaf index "plaats", het eerst in de Vector voorkomt. Indien het "object" niet voorkomt, dan geeft de methode –1 terug. 15 2. KLASSE Vector: methodes contains en indexOf Methode contains • contains(object) Geeft true terug indien het "object" in de Vector voorkomt, anders false. // bevat de vector al dan niet "red"? if ( vector.contains( "red" ) ) System.out.println( "\n\"red\" found at index " + vector.indexOf( "red" ) + "\n" ); else System.out.println( "\n\"red\" not found\n" ); 16 2. KLASSE Vector: methode remove Methode remove • remove(object) - Verwijdert het "object" in de Vector. - Alle objecten die na het verwijderd object staan, worden met één plaats naar voren verschoven. - Indien het "object" meerdere keren in de Vector voorkomt dan wordt enkel het eerst voorkomende "object" verwijdert. - Deze methode geeft true terug indien het object in de Vector voorkwam, anders false. 17 2. KLASSE Vector: methodes (verwijderen van objecten) Methode remove • remove(plaats) - Op index "plaats" wordt het object uit de Vector verwijderd. - Deze methode geeft de referentie van het verwijderd object terug. Methode removeElementAt • removeElementAt(plaats) Idem als de methode remove(plaats) behalve dat deze methode niks teruggeeft (void). Methode removeAllElements • removeAllElements() Alle objecten worden uit de Vector verwijderd. 18 De size wordt op 0 geplaatst. 2. KLASSE Vector: methode remove, removeElementAt en removeAllElements Voorbeeld: ... vector.remove("red"); try { String verwijderdeKleur = (String) vector.remove(1); vector.removeElementAt(0); } // catch exception indien de index < 0 of index >= size() catch (ArrayIndexOutOfBoundsException exception) { exception.printStackTrace(); } vector.removeAllElements(); 19 2. KLASSE Vector: methodes size en capacity Methode size Geeft het aantal objecten in de Vector terug Methode capacity Geeft de capaciteit van de Vector terug capaciteit = aantal objecten dat kan opgeslagen worden zonder meer geheugenruimte te moeten alloceren 20 2. KLASSE Vector: methodes trimToSize en setSize Methode trimToSize De capaciteit wordt gelijkgesteld aan de size. Methode setSize • setSize(nieuweSize) - De size wordt gelijkgesteld aan "nieuweSize" - Indien de size werd verlaagd, dan worden alle objecten vanaf index "nieuweSize" verwijderd. - Indien de size werd verhoogd, dan worden er nieuwe null-objecten op het einde van de Vector toegevoegd (van index "vorigeSize" tot index "nieuweSize"). 21 2. KLASSE Vector: methode ensureCapacity Methode ensureCapacity Stelt de capaciteit van de Vector in. Garandeert dat de Vector een minimum capaciteit heeft. Als de originele capaciteit groter is dan de nieuwe, dan blijft de capaciteit ongewijzigd. 22 2. KLASSE Vector: methode ensureCapacity Methode ensureCapacity als de originele capaciteit kleiner is dan de nieuwe, dan wordt de capaciteit: als "capacity increment" = 0 ("default capacity increment"): als (nieuwe capaciteit > 2 * originele capaciteit) dan capaciteit = nieuwe capaciteit anders capaciteit = 2 * originele capaciteit als "capacity increment" > 0 : als (nieuwe capaciteit > "capacity increment" + originele capaciteit) dan capaciteit = nieuwe capaciteit anders capaciteit = "capacity increment" + originele capaciteit 23 2. OEFENING • Bepaal de uitvoer van het volgend programma: Vector vector = new Vector(); vector.add( "magenta" ); vector.add( "cyan" ); vector.add("red"); System.out.println( "\n1. Size: " + vector.size() + " Capacity: " + vector.capacity() ); vector.trimToSize(); System.out.println( "\n2. Size: " + vector.size() + " Capacity: " + vector.capacity() ); vector.add( "magenta" ); System.out.println( "\n3. Size: " + vector.size() + " Capacity: " + vector.capacity() ); 24 2. OPLOSSING Vector vector = new Vector(); vector.add( "magenta" ); vector.add( "cyan" ); vector.add("red"); System.out.println( "\n1. Size: " + vector.size() + " Capacity: " + vector.capacity() ); vector.trimToSize(); System.out.println( "\n2. Size: " + vector.size() + " Capacity: " + vector.capacity() ); vector.add( "magenta" ); System.out.println( "\n3. Size: " + vector.size() + " Capacity: " + vector.capacity() ); 1. Size: 3 Capacity: 10 2. Size: 3 Capacity: 3 3. Size: 4 Capacity: 6 25 2. OEFENING • Bepaal de uitvoer van het volgend programma: Vector vector = new Vector(5,8); vector.add( "magenta" ); vector.add( "cyan" ); vector.add("red"); System.out.println( "\n1. Size: " + vector.size() + " Capacity: " + vector.capacity() ); vector.trimToSize(); vector.add( "magenta" ); System.out.println( "\n2. Size: " + vector.size() + " Capacity: " + vector.capacity() ); vector.ensureCapacity(18); System.out.println( "\n3. Size: " + vector.size() + " Capacity: " + vector.capacity() ); 26 2. OPLOSSING Vector vector = new Vector(5,8); vector.add( "magenta" ); vector.add( "cyan" ); vector.add("red"); System.out.println( "\n1. Size: " + vector.size() + " Capacity: " + vector.capacity() ); vector.trimToSize(); vector.add( "magenta" ); System.out.println( "\n2. Size: " + vector.size() + " Capacity: " + vector.capacity() ); vector.ensureCapacity(18); System.out.println( "\n3. Size: " + vector.size() + " Capacity: " + vector.capacity() ); 1. Size: 3 Capacity: 5 2. Size: 4 Capacity: 11 3. Size: 4 Capacity: 19 27 2. KLASSE Vector en interface Enumeration private void printVector( Vector vectorToOutput ) { if ( vectorToOutput.isEmpty() ) System.out.print( "vector is empty" ); else { // iterate through the elements System.out.print( "vector contains: " ); Enumeration items = vectorToOutput.elements(); while ( items.hasMoreElements() ) System.out.print( items.nextElement() + " " ); } System.out.println( "\n" ); } De methode printVector zal alle objecten in de vector weergeven op het scherm. 28 2. KLASSE Vector: methodes isEmpty en elements Methode isEmpty Geeft true terug indien de vector leeg is (= size is gelijk aan 0), anders false. Methode elements Geeft een enumeration terug zodat we de vector kunnen doorlopen: alle objecten van index 0 t.e.m. index "size()-1". 29 2. INTERFACE Enumeration De interface Enumeration bevat twee methodes: hasMoreElements en nextElement Methode hasMoreElement Geeft true terug indien de enumeration nog objecten bevat, anders false. Methode nextElement Geeft de referentie terug van het volgend object in de Vector . Werpt een NoSuchElementException indien er geen objecten meer zijn. 30 3. KLASSE Stack Klasse java.util.Stack – In een stack kunnen we objecten plaatsen (push()) en objecten ophalen (pop()). – Stacks werken volgens het LIFO-principe (Last In, First Out), wat betekent dat het laatste object dat we op de stack hebben geplaatst (push()) het eerste is dat we met de methode pop() ontvangen. 31 3. KLASSE Stack Klasse java.util.Stack – De klasse Stack is een subklasse van Vector. Dit betekent dat we een stack kunnen maken en deze kunnen gebruiken zonder ons druk te maken over hoeveel objecten we er uiteindelijk willen in opslaan. 32 3. KLASSE Stack: constructor Er is één constructor voor de klasse Stack: stack1 = new Stack() Creëert een lege stack met capaciteit van 10 objecten en met de "default capacity increment". 33 3. KLASSE Stack: methodes De Klasse Stack bevat vijf eigen methodes: push, pop, isEmpty, peek en search. Methode push Een object op de stack plaatsen. Methode pop Een object van de stack afhalen. Methode isEmpty Geeft true terug indien de stack leeg is, anders false. 34 3. KLASSE Stack: methodes Methode peek • peek() Geeft de referentie van het object terug dat bovenaan op de stack staat (= top van de stack). Methode search • search(object) Geeft een geheel getal terug waarmee we aan de weet komen hoever onder in de stack het "object" zich bevindt. De top van de stack wordt als afstand één beschouwd. Indien het "object" niet voorkomt, dan geeft de methode –1 terug. 35 3. KLASSE StackTest import java.util.*; public class StackTest { public StackTest() { Stack stack = new Stack(); Een lege Stack wordt gecreëerd. // objecten creëren om in de stack te plaatsen Boolean bool = Boolean.TRUE; Character character = new Character( '$' ); Integer integer = new Integer( 34567 ); methode String string = "hello"; push voegt een Object op de top van de Stack toe. // push methode gebruiken stack.push( bool ); printStack( stack ); stack.push( character ); printStack( stack ); stack.push( integer ); printStack( stack ); stack.push( string ); printStack( stack ); 36 3. KLASSE StackTest // verwijder objecten van de stack try { Object removedObject = null; methode pop verwijdert het object dat op de top van de Stack staat. while ( true ) { removedObject = stack.pop(); // gebruik pop methode System.out.println( removedObject.toString() + " popped" ); printStack( stack ); } } // catch exception indien methode pop op een lege stack // werd uitgevoerd. catch ( EmptyStackException emptyStackException ) { emptyStackException.printStackTrace(); } } //einde constructor StackTest 37 3. KLASSE StackTest Stack erft van private void printStack( Stack stack ) Vector, dus de { klasse Stack kan ook if ( stack.isEmpty() ) de methode System.out.print( "stack is empty" ); elements else gebruiken. Alle { objecten van de stack System.out.print( "stack contains: " ); worden doorlopen Enumeration items = stack.elements(); door behulp van // stack doorlopen Enumeration. while ( items.hasMoreElements() ) System.out.print( items.nextElement() + " " ); } System.out.println( "\n" ); // naar de volgende lijn } public static void main( String args[] ) { new StackTest(); } } // einde klasse StackTest De top van de Stack wordt als laatste weergegeven op het scherm. 38 3. KLASSE StackTest stack contains: true stack contains: true $ stack contains: true $ 34567 stack contains: true $ 34567 hello hello popped stack contains: true $ 34567 hello 34567 $ true 34567 popped stack contains: true $ $ popped stack contains: true true popped stack is empty java.util.EmptyStackException at java.util.Stack.peek(Stack.java:79) at java.util.Stack.pop(Stack.java:61) at StackTest.<init>(StackTest.java:32) at StackTest.main(StackTest.java:63) 39 4. KLASSE Hashtable : inleiding Klasse java.util.Hastable – Een hash-tabel wijst sleutels toe aan waarden. De waarden en sleutels kunnen gelijk welk Java-object zijn. – Vb.: hashtable "Werknemers" sleutel 123 566 411 899 455 178 … waarde KETERS SANDRA WAERLOP JURGEN 40 4. KLASSE Hashtable : methode get Methode get – Aan de hand van een sleutel kunnen we de overeenkomstige waarde ophalen Object get(Object sleutel) • Geeft de overeenkomstige waarde terug of geeft null terug indien de sleutel niet in de hash-tabel voorkomt. • Werpt een NullPointerException indien de sleutel gelijk is aan null. 41 4. KLASSE Hashtable : hashing – Een hash-tabel is een gegevensstructuur dat gebruik maakt van hashing: • De sleutel wordt omgezet naar een array index. Met deze index wordt de waarde opgezocht. Deze basistechniek heet hashing. • Indien twee verschillende sleutels dezelfde array index opleveren dan spreekt men van een collision. 42 4. KLASSE Hashtable : hash bucket – Om collisions te voorkomen maakt JAVA gebruik van "hash bucket (= emmer)": • De hash-tabel bestaat uit cellen. Elke cel is een "hash bucket". Een koppel sleutel-waarde wordt toegekend aan een bepaalde "bucket". De techniek hashing bepaalt in welke bucket het koppel sleutel-waarde terechtkomt. 43 4. KLASSE Hashtable : methode put Methode put – We kunnen een koppel sleutel-waarde in de hash-tabel zetten door de methode put Object put(Object sleutel, Object waarde) • Geeft de voorgaande waarde terug of geeft null terug indien de sleutel nog niet in de hash-tabel voorkwam. • Werpt een NullPointerException indien de sleutel of de waarde gelijk is aan null. 44 4. KLASSE Hashtable : capaciteit en laadfactor Hash-tabellen hebben een capaciteit en een laadfactor. • De capaciteit is het aantal emmers ("buckets") dat de hash-tabel bevat. • De laadfactor is een getal tussen 0 en 1. Deze vertelt ons hoe vol een hash-tabel kan worden voordat de capaciteit wordt verhoogd. Als we de laadfactor niet opgeven wanneer we een hash-tabel creëren, wordt deze ingesteld op 0.75. Dit betekent dat als het aantal vermeldingen 75% van de capaciteit bereikt, de capaciteit wordt verhoogd met 45 de methode rehash(). 4. KLASSE Hashtable: constructoren Er zijn meerdere constructoren voor de klasse Hashtable: hashtable1 = new Hashtable() Creëert een lege hash-tabel met een capaciteit van 11 en een laadfactor 0.75. hashtable2 = new Hashtable(capaciteit) Creëert een lege hash-tabel met een capaciteit aangegeven door de integer “capaciteit“ en een laadfactor 0.75. Hashtable3 = new Hashtable(capaciteit, laadfactor) Creëert een lege hash-tabel met een capaciteit aangegeven door de integer “capaciteit“ en een laadfactor aangegeven door de float “laadfactor“. 46 4. KLASSE Hashtable : inleiding – Hash-tabellen kunnen meer dan één gegevenstype opslaan. Terwijl Stringen StringBuffer-objecten alleen tekens kunnen bevatten en arrays alleen elementen van hetzelfde type kunnen hebben, kunnen we de gegevenstypen, die zijn opgeslagen in een hash-tabel, combineren. 47 4. KLASSE Hashtable: VOORBEELD Voorbeeld – Van een ingegeven zin wordt er afgebeeld hoeveel keer een bepaald woord erin voorkomt. – De sleutels zijn de woorden. De overeenkomstige waarden zijn gehele getallen. Deze getallen stellen het aantal keer, dat een woord in de zin voorkomt, voor. 48 4. KLASSE Hashtable: VOORBEELD 49 4. KLASSE WordTypeCount import java.util.*; … public class WordTypeCount extends JFrame { … private Hashtable table; public WordTypeCount() { … table = new Hashtable(); Een lege hashable creëren. 50 4. KLASSE WordTypeCount goButton = new JButton( "Go" ); goButton.addActionListener( new ActionListener() { // anonieme innerklasse public void actionPerformed( ActionEvent event ) { createTable(); display.setText( createOutput() ); } } // einde anonieme innerklasse ); // einde oproep naar addActionListener … }// einde constructor Indien de gebruiker op de button "Go" klikt, dan zullen de methodes createTable en createOutput opgeroepen 51 worden. 4. KLASSE WordTypeCount // hash-tabel opvullen met invoer van de gebruiker private void createTable() { String input = inputField.getText(); StringTokenizer words = new StringTokenizer( input, " \n\t\r" ); while ( words.hasMoreTokens() ) { String word = words.nextToken().toLowerCase(); // indien de sleutel "word" reeds in de hashtable "table" voorkomt. if ( table.containsKey( word ) ) { // overeenkomstige waarde opvragen en met één verhogen: Integer count = (Integer) table.get( word ); table.put( word, new Integer( count.intValue() + 1 ) ); } else // de sleutel "word" en waarde 1 in de hash-tabel zetten table.put( word, new Integer( 1 ) ); Uitleg: zie } // einde while volgende slide 52 } // einde methode createTable 4. KLASSE WordTypeCount if ( table.containsKey( word ) ) { // overeenkomstige waarde opvragen en met één verhogen: Integer count = (Integer) table.get( word ); table.put( word, new Integer( count.intValue() + 1 ) ); } else // de sleutel "word" en waarde 1 in de hash-tabel zetten table.put( word, new Integer( 1 ) ); Indien het woord "word" (= sleutel) reeds in de hash-tabel voorkomt, dan wordt zijn overeenkomstige waarde (count) met één verhoogd en terug in de hash-tabel geplaatst. Anders wordt het woord "word" (=sleutel) en de waarde 1 in de hash-tabel geplaatst. De methode intValue zet de waarde van de Integer om 53 naar een int. 4. KLASSE WordTypeCount // string creëren die alle sleutels en overeenkomstige waarden // van de hash-tabel bevat Geeft een enumeration private String createOutput() terug zodat we de hash{ table kunnen doorlopen. String output = ""; De enumeration bevat Enumeration keys = table.keys(); alle sleutels. // de sleutels doorlopen while ( keys.hasMoreElements() ) { Object currentKey = keys.nextElement(); // het koppel sleutel-waarde toevoegen aan de string output += currentKey + "\t" + table.get( currentKey ) + "\n"; } output += "size: " + table.size() + "\n"; output += "isEmpty: " + table.isEmpty() + return output; } // einde methode createOutput Geeft het aantal koppels sleutels"\n"; waarden, die de hash-tabel bevat, 54 terug 5. KLASSE Properties : inleiding Klasse java.util.Properties – Een properties-tabel is een hash-tabel waarbij de sleutels altijd een String zijn. • De klasse Properties is een subklasse van Hashtable. – Doel van Properties: deze klasse biedt een eenvoudige manier om op tekst gebaseerde gegevens van bestand te laden en 55 op te slaan. 5. KLASSE Properties : methode getProperty Methode getProperty – Aan de hand van een sleutel kunnen we de overeenkomstige waarde ophalen String getProperty(String sleutel) • Geeft de overeenkomstige waarde terug of geeft null terug indien de sleutel niet in de properties-tabel voorkomt. 56 5. KLASSE Properties : methode setProperty Methode setProperty – We kunnen een koppel sleutel-waarde in de property zetten door de methode setProperty Object setProperty(String sleutel, String waarde) • Geeft de voorgaande waarde terug of geeft null terug indien de sleutel nog niet in de properties-tabel voorkwam. 57 5. KLASSE Properties: VOORBEELD Voorbeeld – De gebruiker kan op de volgende buttons klikken: Put: koppel sleutel-waarde toevoegen of een waarde wijzigen. Clear: de properties-tabel wissen. Get property: de overeenkomstige waarde opvragen. Save: de properties-tabel bewaren op bestand. Load: de properties-tabel laden van bestand.58 5. KLASSE Properties: VOORBEELD 59 5. KLASSE Properties: VOORBEELD 60 5. KLASSE PropertiesTest import java.io.*; import java.util.*; ... public class PropertiesTest extends JFrame { private Properties table; ... // opmaak van GUI om de Property-tabel uit te testen public PropertiesTest() Een lege { ... properties-tabel table = new Properties(); ... creëren. northSubPanel.add( new JLabel( "Property value" ) ); valueField = new JTextField( 10 ); northSubPanel.add( valueField ); northSubPanel.add( new JLabel( "Property name (key)" ) ); nameField = new JTextField( 10 ); 61 northSubPanel.add( nameField ); 5. ... KLASSE PropertiesTest JButton putButton = new JButton( "Put" ); southPanel.add( putButton ); putButton.addActionListener(new ActionListener() { // anonieme innerklasse // zet koppel naam-waarde in Properties tabel public void actionPerformed( ActionEvent event ) { Object value = table.setProperty( nameField.getText(), valueField.getText() ); if ( value == null ) showstatus( "Put: " + nameField.getText() + " " + valueField.getText() ); else showstatus( "Put: " + nameField.getText() + " " + valueField.getText() + "; Replaced: " + value ); listProperties(); } } // einde anonieme innerklasse ); Indien de gebruiker op de button "Put" klikt dan zal een koppel sleutel-waarde worden toegevoegd of indien de sleutel reeds bestaat in de properties-tabel dan zal zijn 62 overeenkomstige waarde gewijzigd worden. 5. KLASSE PropertiesTest JButton clearButton = new JButton( "Clear" ); southPanel.add( clearButton ); clearButton.addActionListener( new ActionListener() { // anonieme innerklasse // methode clear gebruiken om de properties-tabel te wissen. public void actionPerformed( ActionEvent event ) { De methode clear wist de properties-tabel table.clear(); showstatus( "Table in memory cleared" ); listProperties(); } } // einde anonieme innerklasse ); // einde oproep naar addActionListener 63 5. KLASSE PropertiesTest JButton getPropertyButton = new JButton( "Get property" ); ... // methode getProperty gebruiken om de overeenkomstige waarde // op te halen. public void actionPerformed( ActionEvent event ) { Object value = table.getProperty( nameField.getText() ); if ( value != null ) showstatus( "Get property: " + nameField.getText() + " " + value.toString() ); else showstatus( "Get: " + nameField.getText() + " not in table" ); listProperties(); } } // einde anonieme innerklasse ); Indien de gebruiker de sleutel ingeeft en op de button "Get property" klikt dan zal, indien de sleutel in de properties-tabel 64 voorkomt, de overeenkomstige waarde worden weergegeven. 5. KLASSE PropertiesTest JButton saveButton = new JButton( "Save" ); ... public void actionPerformed( ActionEvent event ) { // de inhoud van de properties-tabel bewaren op bestand try { FileOutputStream output = new FileOutputStream( "props.dat" ); table.store( output, "Sample Properties" ); output.close(); Deze methode store listProperties(); } zal alle koppels // problemen met file output opvangen: sleutels-waarden van catch( IOException ioException ) de properties-tabel { ioException.printStackTrace(); } } } // einde anonieme innerklasse ); "table" bewaren op het bestand "props.dat". 65 5. KLASSE PropertiesTest JButton loadButton = new JButton( "Load" ); ... public void actionPerformed( ActionEvent event ) { // de inhoud van de tabel laden try { FileInputStream input = new FileInputStream( "props.dat" ); table.load( input ); Deze methode input.close(); load zal alle listProperties(); } koppels sleutels// problemen met file output opvangen: waarden van het catch( IOException ioException ) bestand { ioException.printStackTrace();} } } // einde anonieme innerklasse ); "props.dat" laden in de properties-tabel "table". 66 5. KLASSE PropertiesTest // de koppels sleutel-waarden van de properties-tabel weergeven public void listProperties() { StringBuffer buffer = new StringBuffer(); Geeft een String name, value; Enumeration enumeration = table.propertyNames(); enumeration while ( enumeration.hasMoreElements() ) terug zodat { we de name = enumeration.nextElement().toString(); propertiesvalue = table.getProperty( name ); tabel kunnen buffer.append( name ).append( '\t' ); buffer.append( value ).append( '\n' ); } displayArea.setText( buffer.toString() ); doorlopen. De enumeration bevat alle sleutels. } 67 6. BIT-MANIPULATIES EN BITWISE OPERATOREN Inleiding – Bit = de allerkleinste geheugeneenheid, die een 0 of een 1 kan bevatten. – Byte = (in het algemeen) elementaire geheugeneenheid van een computer. Een byte is opgebouwd uit 8 bits. 68 6. BIT-MANIPULATIES EN BITWISE OPERATOREN Inleiding – Bit-manipulatie is nodig indien we rechtstreeks met de hardware wensen te communiceren (bv. we willen een operating system, netwerk software, … , programmeren.) – We voeren bit-manipulatie uit door gebruik te maken van bitwise operatoren. 69 6. BITWISE OPERATOREN – Bitwise EN-operator (&) De bitwise en-operator & heeft als resultaat 1 als beide bits gelijk zijn aan 1. Als één van beide bits gelijk is aan 0, of beide zijn gelijk aan 0, dan levert de bitwise en-operator & ook 0 op. Bit 1 0 1 0 1 Bit 2 Bit 1 & Bit 2 0 0 0 0 1 0 1 1 Bitwise EN-operator (&) 70 6. BITWISE OPERATOREN – Bitwise EN-operator (&) Voorbeeld: 100 & 12 geeft 4 als resultaat: 1100100 // binaire voorstelling van 100 & 1100 // binaire voorstelling van 12 ------------------100 // binaire voorstelling van 4 100 & 12 geeft ook 1 als resultaat: de meest significante bit van het geheel getal 4 is 1 if (( 100 & 12 ) == 0) … 71 6. BITWISE OPERATOREN – Bitwise inclusieve OF operator (|) De bitwise inclusieve of-operator | heeft als resultaat 1 als één van beide bits gelijk is aan 1, of beide zijn gelijk aan 1. Als beide bits gelijk zijn aan 0, dan levert de bitwise inclusieve of-operator | 0 op. Bit 1 0 1 0 1 Bit 2 Bit 1 | Bit 2 0 0 0 1 1 1 1 1 Bitwise inclusieve OF-operator (|). 72 6. BITWISE OPERATOREN – Bitwise exclusieve OF operator (^) De bitwise exclusieve of-operator ^ heeft als resultaat 1 als één van beide bits gelijk is aan 1. Als beide bits gelijk zijn aan 0 of 1, dan levert de bitwise exclusieve of-operator ^ 0 op. Bit 1 0 1 0 1 Bit 2 Bit 1 ^ Bit 2 0 0 0 1 1 1 1 0 Bitwise exclusieve OF-operator (^). 73 6. BITWISE OPERATOREN – "Left shift" (<<) x << y De bits van x worden y-maal naar links verschoven. De bits worden achteraan aangevuld met 0. voorbeeld: 1 << 6 De voorstelling van getal 1 in bits is: 00000000 00000000 00000000 00000001 Er worden 6 plaatsen naar links verschoven: 00000000 00000000 00000000 01000000 74 6. BITWISE OPERATOREN – "Signed rigth shift" (>>) x >> y De bits van x worden y-maal naar rechts verschoven. Indien x negatief is dan worden de bits vooraan aangevuld met 1, anders met 0. – "Unsigned rigth shift " (>>>) x >>> y De bits van x worden y-maal naar rechts verschoven. De bits worden vooraan aangevuld met 0. 75 6. BITWISE OPERATOREN – "bitwise complement" (~) Alle 0 bits worden omgezet naar 1 en alle 1 bits worden omgezet naar 0. Bit 0 1 ~Bit 1 0 Bitwise complement (~) 76 6. BIT-MANIPULATIES EN BITWISE OPERATOREN Voorbeeld 1 – Van een ingegeven geheel getal zijn overeenkomstige bit-representatie weergeven. 77 6. KLASSE PrintBits ... public class PrintBits extends JFrame { private JTextField outputField; public PrintBits() { ... container.add( new JLabel( "Enter an integer " ) ); JTextField inputField = new JTextField( 10 ); ... public void actionPerformed( ActionEvent event ) { int value = Integer.parseInt( event.getActionCommand() ); outputField.setText( getBits( value ) ); } } // einde anonieme innerklasse ); ... } // einde constructor Zet een String om naar een int, vervolgens wordt de int doorgegeven aan de private methode getBits. 78 Deze methode geeft de bit-represenatie van de int terug. 6. KLASSE PrintBits // geeft de bit-representatie van de int "value" terug private String getBits( int value ) { // creëert een int met het meest linkse bit 1. De overige 31 // bits zijn 0. int displayMask = 1 << 31; 1 << 31 is gelijk aan 10000000 00000000 00000000 00000000 StringBuffer buffer = new StringBuffer( 35 ); // buffer // voor output // Voor elke bit 0 of 1 aan de buffer toevoegen for ( int bit = 1; bit <= 32; bit++ ) { // displayMask gebruiken om een bit af te zonderen buffer.append( ( value & displayMask ) == 0 ? '0' : '1' ); value <<= 1; // shift value met één positie naar links if ( bit % 8 == 0 ) buffer.append( ' ' ); // Na elke 8 bits een spatie toevoegen } return buffer.toString(); Uitleg: zie volgende slide } // einde methode getBits ... 79 UITLEG: buffer.append( ( value & displayMask ) == 0 ? '0' : '1' ); value <<= 1; // m.a.w. value = value << 1; Stel dat value gelijk is aan 2 000 000 000 (01110111 00110101 10010100 00000000) Wanneer value en displayMask (1<<31) vergeleken worden met de bitwise EN-operator (&) wordt de meest significante bit van het resultaat teruggegeven. 01110111 00110101 10010100 00000000 & 10000000 00000000 0000000 00000000 is 00000000 00000000 0000000 00000000 0 value = value << 1, dus de bits van value worden met één plaats naar links opgeschoven: 11101110 01101011 00101000 00000000. 11101110 01101011 00101000 00000000 & 10000000 00000000 0000000 00000000 is 10000000 00000000 0000000 00000000 1 Etc. 80 6. BIT-MANIPULATIES EN BITWISE OPERATOREN Voorbeeld 2 – De gebruiker kan op de volgende buttons klikken: And: het resultaat van de bitwise en-operator & wordt in bits en in geheel getal weergegeven. Analoog voor Inclusive OR, Exclusive OR en Complement. 81 6. BIT-MANIPULATIES EN BITWISE OPERATOREN 82 6. KLASSE MicsBitOps ... (value1 & value2) public class MiscBitOps extends JFrame {... heeft een geheel getal als public MiscBitOps() resultaat. {... JButton andButton = new JButton( "AND" ); ... public void actionPerformed( ActionEvent event ) { setFields(); resultField.setText( Integer.toString( value1 & value2 ) ); bits3Field.setText( getBits( value1 & value2 ) ); } } // einde anonieme innerklasse ); JButton inclusiveOrButton = new JButton( "Inclusive OR" ); ... resultField.setText( Integer.toString( value1 | value2 ) ); bits3Field.setText( getBits( value1 | value2 ) ); } } // einde anonieme innerklasse ); 83 6. KLASSE MicsBitOps JButton exclusiveOrButton = new JButton( "Exclusive OR" ); ... resultField.setText( Integer.toString( value1 ^ value2 ) ); bits3Field.setText( getBits( value1 ^ value2 ) ); } } // einde anonieme innerklasse ); JButton complementButton = new JButton( "Complement" ); ... int value = Integer.parseInt( input1Field.getText() ); resultField.setText( Integer.toString( ~value ) ); bits1Field.setText( getBits( value ) ); bits3Field.setText( getBits( ~value ) ); } } // einde anonieme innerklasse ); ... } // end constructor private void setFields() { value1 = Integer.parseInt( input1Field.getText() ); value2 = Integer.parseInt( input2Field.getText() ); bits1Field.setText( getBits( value1 ) ); 84 bits2Field.setText( getBits( value2 ) ); } ... 6. BITWISE TOEKENNING OPERATOREN – Bitwise toekenning operatoren Bitwise toekenning operatoren &= |= ^= <<= >>= >>>= Bitwise EN toekenning operator. Bitwise inclusieve OF toekenning operator. Bitwise exclusieve OF toekenning operator. Left-shift toekenning operator. Signed right-shift toekenning operator. Unsigned right-shift toekenning operator. Bitwise toekenning operatoren. 85 6. Voorbeeld 3: KLASSE BitShift ... int value = Integer.parseInt( valueField.getText() ); value <<= 1; ... value >>= 1; ... value >>>= 1; ... Starten met getal –2147483648 Één positie naar rechts opschuiven (signed) Starten met getal –2147483648 Één positie naar rechts opschuiven (unsigned) 86 7. KLASSE BITSET Klasse java.util.BitSet – BitSet is een groeibare array van bits. Deze bits stellen vlaggen voor die op true ( = 1 ) of op false ( = 0 ) staan. 87 7. KLASSE BITSET: bitwise operatoren – Bitwise operatoren kunnen op bitsets als volgt worden toegepast: • Stel dat b1 en b2 bitsets zijn: b1.and(b2); De bitwise EN-operator wordt bit per bit uitgevoerd (b1[0] & b2[0], b1[1]&b2[1],…) en het resultaat wordt bewaard in de bitset b1. b1.or(b2); //Bitwise inclusieve OF operator b1.xor(b2); //Bitwise exclusieve OF operator 88 7. KLASSE BitSet: constructoren Er zijn twee constructoren voor de klasse BitSet: bitSet1 = new BitSet() Creëert een lege bitset (= alle bits staan op false). In het geheugen is er reeds plaats om 64 bits te bewaren (index 0 t.e.m. 63). bitSet2 = new BitSet(aantal) Creëert een lege bitset. In het geheugen is er reeds plaats om “aantal“ bits te bewaren. 89 7. KLASSE BitSet: voorbeelden van methoden Voorbeelden van methoden van de klasse BitSet: bitSet1 = new BitSet(); int size = bitSet1.size(); // size = 64 int lengte = bitSet1.length(); // lengte = 0 // (= logische size = geeft de index van de hoogste bit die op true staat + 1 ) bitSet1.set(3); //zet de bit op index 3 op true bitSet1.set(10); //zet de bit op index 10 op true; lengte = bitSet1.length(); // lengte = 11 if (bitSet1.get(3)) ... // geeft true terug indien de bit //op index 3 op true staat, anders false bitSet1.clear(3); //zet de bit op index 3 op false. 90 7. KLASSE BitSet: voorbeelden van methoden Voorbeelden van methoden van de klasse BitSet: bitSet1 = new BitSet(); bitSet2 = new BitSet(500); // bitSet1.toString() geeft “{}“ terug. bitSet1.set(4); bitSet1.set(10); // bitSet1.toString() geeft “{4,10}“ terug. bitSet2.set(4); bitSet2.set(10); if (bitSet1.equals(bitSet2)) ... // geeft true terug omdat // de bitsets identiek zijn 91 7. KLASSE BitSetTest Voorbeeld – Alle priemgetallen tussen 2 en 1023 worden weergegeven. Tevens kan de gebruiker een getal ingeven en krijgt op het scherm te zien of het getal al dan niet een priemgetal is. 92 7. KLASSE BitSetTest 93 7. KLASSE BitSetTest import java.util.*; ... public class BitSetTest extends JFrame { private BitSet sieve; ... public BitSetTest() // schermopmaak (constructor) { super( "BitSets" ); sieve = new BitSet( 1024 ); ... Een lege bitset wordt gecreëerd met size 1024 94 7. KLASSE BitSetTest // textfield waar de gebruiker een getal kan ingeven tussen 2 // en 1023. Indien de gebruiker een getal ingeeft groter dan // 1023 dan krijgt hij als bericht dat het getal geen // priemgetal is! Geeft true terug inputField = new JTextField( 10 ); indien de bit op ... index "value" op inputField.addActionListener( true staat, anders new ActionListener() false. { // innerklasse // bepaalt indien het getal al dan niet een priemgetal is public void actionPerformed( ActionEvent event ) { int value = Integer.parseInt( inputField.getText() ); if ( sieve.get( value ) ) statusLabel.setText( value + " is a prime number" ); else statusLabel.setText(value + " is not a prime number"); } } // einde innerklasse 95 ); // einde oproep addActionListener 7. KLASSE BitSetTest ... // geeft de size van de bitset terug int size = sieve.size(); // zet alle bits van 2 to 1023 op true for ( int i = 2; i < size; i++ ) Zet de bit op sieve.set( i ); index "i" op true // voer Sieve van Eratosthenes uit int finalBit = ( int ) Math.sqrt( size ); for ( int i = 2; i < finalBit; i++ ) if ( sieve.get( i ) ) for ( int j = 2 * i; j < size; j += i ) sieve.clear( j ); Zet de bit op De methoden get, set en clear werpen index "j" op false een IndexOutOfBoundsException 96 indien hun argument negatief is. 7. KLASSE BitSetTest // Geeft alle priemgetallen tussen 2 en 1023 weer int counter = 0; for ( int i = 2; i < size; i++ ) if ( sieve.get( i ) ) { primesArea.append( String.valueOf( i ) ); primesArea.append( ++counter % 7 == 0 ? "\n" : "\t" ); } ... 97