Συμβολοσειρές
- Οι συμβολοσειρές παριστάνονται από την κλάση String
- Όλες οι σταθερές συμβολοσειρές στο πρόγραμμα είναι αντικείμενα της κλάσης String
- Τα αντικείμενα της κλάσης String είναι αμετάβλητα
- Μεταβλητές συμβολοσειρές υποστηρίζονται από την κλάση StringBuffer
- Η γλώσσα Java υποστηρίζει τη αλυσιδωτή σύνδεση συμβολοσειρών με τους τελεστές + και +=
- Όταν οι παραπάνω τελεστές εφαρμοστούν σε αντικείμενα που δεν είναι τύπου
String, τότε αυτά μετατρέπονται σε String με την κλήση της μεθόδου toString().
- Επίσης, ορισμένες μέθοδοι έχουν οριστεί να λαμβάνουν ως όρισμα Object και προσπαθούν εσωτερικά να το μετατρέψουν σε συμβολοσειρά με την κλήση της toString().
Συμβολοσειρές: παράδειγμα
class Book {
public String toString() { return "Book"; }
static public void main(String args[]) {
var b = new Book();
String k = "*" + b + "*";
System.out.println(k);
System.out.println(b);
}
}
Συμβολοσειρές πολλαπλών γραμμών
Μπορούμε να παραστήσουμε συμβολοσειρές πολλαπλών γραμμών με
τριπλά εισαγωγικά.
String html = """
<html>
<body>
<h1>Welcome to my page</h1>
<p>This is a paragraph.</p>
</body>
</html>
""";
String: μέθοδοι κατασκευής
- String()
- Κατασκευάζει μια άδεια συμβολοσειρά.
- String(char[] value)
- Κατασκευάζει μια συμβολοσειρά από
τον πίνακα value.
- String(char[] value, int offset, int count)
- Κατασκευάζει μια συμβολοσειρά από count στοιχεία του πίνακα value αρχίζοντας από τη θέση offset.
- String(String original)
- Κατασκευάζει ένα αντίγραφο συμβολοσειράς
- String(StringBuffer buffer)
- Κατασκευάζει μια συμβολοσειρά από ένα αντικείμενο StringBuffer
String: μέθοδοι επεξεργασίας
Οι θέσεις σε μια συμβολοσειρά αριθμούνται από το 0.
Η μη ύπαρξη θέσης συμβολίζεται με το -1.
- String substring(int beginIndex)
- Επιστρέφει το τμήμα που αρχίζει στη θέση beginIndex
- String substring(int beginIndex, int endIndex)
- Επιστρέφει το τμήμα που αρχίζει στη θέση beginIndex
και τελειώνει στη θέση endIndex - 1
- char charAt(int index)
- Επιστρέφει το χαρακτήρα στη θέση index
- String concat(String string2)
- Επιστρέφει τη συμβολοσειρά ενωμένη με το string2
String: μέθοδοι ερωτήσεων
- int length()
- Μήκος
- boolean equals(String string2)
- Σύγκριση
- boolean StartsWith(String string2)
- Σύγκριση αρχής
- boolean endsWith(String string2)
- Σύγκριση τέλους
- int compareTo(String string2)
- Λεξικογραφική σύγκριση (απλή)
- int indexOf(String string2)
- Επιστρέφει τη θέση της συμβολοσειράς string2
String: μέθοδοι μετατροπής
- static String valueOf(int i)
- Μετατρέπει το όρισμα i σε συμβολοσειρά
- static String valueOf(double d)
- Μετατρέπει το όρισμα d σε συμβολοσειρά
- static String valueOf(boolean b)
- Μετατρέπει το όρισμα b σε συμβολοσειρά
- static String valueOf(long l)
- Μετατρέπει το όρισμα l σε συμβολοσειρά
- static String valueOf(float f)
- Μετατρέπει το όρισμα f σε συμβολοσειρά
- static String valueOf(char c)
- Μετατρέπει το όρισμα c σε συμβολοσειρά
Η κλάση StringBuffer
- Η κλάση StringBuffer υλοποιεί μεταβλητές συμβολοσειρές
- Υποστηρίζει τις περισσότερες μεθόδους της String και μερικές πρόσθετες
- StringBuffer append(String string2)
- Προσθήκη της συμβολοσειράς string2 στο τέλος
- StringBuffer insert(int offset, String string2)
- Προσθήκη της συμβολοσειράς string2 στη θέση offset
- StringBuffer delete(int start, int end)
- Διαγραφή των χαρακτήρων από τη θέση start μέχρι την end - 1
- StringBuffer replace(int start, int end, String string2)
- Αντικατάσταση των χαρακτήρων από τη θέση start μέχρι την end - 1 με τη συμβολοσειρά string2
Εσωτερική χρήση της StringBuffer
Η κλάση StringBuilder παρέχει τις ίδιες δυνατότητες με την
StringBuffer, χωρίς όμως να παρέχει ασφάλεια σε πολυνηματική
επεξεργασία.
Η κλάση StringBuilder χρησιμοποιείται και από το μεταγλωττιστή για την
υλοποίηση ένωσης συμβολοσειρών.
Η ακολουθία
μεταγλωττίζεται εσωτερικά σε
x = new StringBuilder().append("a").append(4).append("c").toString()
Πλαίσια συλλογών
- Μια συλλογή (collection) είναι ένα σύνολο από αντικείμενα
- Ένα πλαίσιο συλλογών (collection framework)
υποστηρίζει την αρχιτεκτονικά ομογενή παράσταση και χειρισμό των συλλογών,
ανεξάρτητα από την υλοποίησή τους.
Πλεονεκτήματα
Τα πλεονεκτήματα της υποστήριξης και του προγραμματισμού με βάση ένα
πλαίσιο συλλογών είναι:
- Μείωση του κόστους υλοποίησης
- Βελτίωση της απόδοσης
- Δυνατότητα εύκολης αλλαγής εναλλακτικών υλοποιήσεων
- Διαλειτουργικότητα μεταξύ άσχετων τμημάτων
- Ευκολότερη εκμάθηση του πλαισίου και βιβλιοθηκών που το χρησιμοποιούν
- Ευκολότερος σχεδιασμός βιβλιοθηκών
- Επαναχρησιμοποίηση λογισμικού
Το πλαίσιο συλλογών της Java
Το πλαίσιο συλλογών της βιβλιοθήκης της Java περιλαμβάνει:
- Διεπαφές συλλογών
- Υλοποιήσεις συλλογών
- Συσκευασίες συλλογών που αλλάζουν τη συμπεριφορά τους
- Υλοποιήσεις ευκολίας εξειδικευμένων συλλογών
- Αφηρημένες υλοποιήσεις συλλογών
- Αλγορίθμους
- Επαναλήπτες
- Διεπαφές σύγκρισης
- Εξαιρέσεις
Διεπαφές συλλογών
- Οι διεπαφές που υποστηρίζονται από τη βιβλιοθήκη χωρίζονται σε
δύο μεγάλες κατηγορίες:
- Συλλογές
- απεικονίσεις (mappings)
- Οι διεπαφές των συλλογών είναι:
- Collection, που επεκτείνεται από τις διεπαφές:
- Set (σύνολο μοναδικών στοιχείων)
- List (ακολουθία)
- SortedSet (ταξινομημένο σύνολο μαναδικών στοιχείων)
- Οι διεπαφές των απεικονίσεων είναι:
- Map, και η επέκταση
- SortedMap
Υλοποιήσεις συλλογών
-
Οι ακολουθίες υλοποιούνται με τους παρακάτω τρόπους:
- Πίνακας
- Συνδεδεμένη λίστα (linked list)
-
Τα σύνολα και οι απεικονίσεις υλοποιούνται με τους παρακάτω τρόπους:
- Πίνακας κατακερματισμού (hash table)
- Ισοζυγισμένο δέντρο (balanced tree)
- Συνδυασμός συνδεδεμένης λίστας και πίνακα κατακερματισμού
Διαθέσιμες υλοποιήσεις στη Java
Για τις διεπαφές των συλλογών υπάρχουν οι παρακάτω υλοποιήσεις:
- Set:
- HashSet, TreeSet, LinkedHashSet
- SortedSet:
- TreeSet
- List:
- ArrayList, LinkedList
- Map:
- HashMap, TreeMap, LinkedHashMap
- SortedMap:
- TreeMap
Πίνακας διεπαφών και υλοποιήσεων
|
Υλοποιήσεις |
ΠΚ | Πίνακας |
ΙΔ | ΣΛ |
ΣΛ και ΠΚ |
Διεπαφές |
Set | HashSet |
|
TreeSet |
|
LinkedHashSet |
SortedSet | |
|
TreeSet |
|
|
List | |
ArrayList |
|
LinkedList |
|
Map |
HashMap |
|
TreeMap |
|
LinkedHashMap |
SortedMap |
|
|
TreeMap |
|
|
(Οι υλοποιήσεις που συνδιάζουν συνδεδεμένη λίστα και πίνακα κατακερματισμού
επιτρέπουν την πρόσβαση των στοιχείων με τη σειρά που έγινε η εισαγωγή τους.)
Διάγραμμα UML
Η δομή των διεπαφών και κλάσεων που έχουμε εξετάσει μπορεί να παρασταθεί
σε μορφή UML ως εξής.
Σημείωση: στην πράξη η υλοποίηση της Java χρησιμοποιεί και άλλες ενδιάμεσες
κλάσεις, όπως AbstractCollection, AbstractSequentialList, AbstractSet.
Collection: επεξεργασία
Η γενικευμένη διεπαφή
ορίζει μεταξύ άλλων τις παρακάτω μεθόδους
(κατά περίπτωση επιστρέφουν αληθές αν η συλλογή μεταβλήθηκε):
- void clear()
- Αφαιρεί όλα τα αντικείμενα από τη συλλογή
- boolean add(E o)
- Προσθήκη στοιχείου
- boolean addAll(Collection <? extends E> c)
- Προσθήκη συλλογής
- boolean remove(Object o)
- Αφαίρεση στοιχείου
- boolean removeAll(Collection <?> c)
- Αφαίρεση συλλογής
Collection: ερωτήσεις
- boolean contains(Object o)
- Επιστρέφει αληθές αν το στοιχείο περιέχεται
- boolean containsAll(Collection <?> c)
- Επιστρέφει αληθές αν τα στοιχεία της συλλογής περιέχονται
- Iterator <E> iterator()
- Επιστρέφει έναν επαναλήπτη για διάσχιση της συλλογής
- boolean isEmpty()
- Επιστρέφει αληθές αν η συλλογή είναι άδεια
- int size()
- Επιστρέφει τον αριθμό των στοιχείων στη συλλογή
Παράδειγμα της διεπαφής Collection
import java.util.Collection;
import java.util.LinkedList;
public class CollectionTest <E> {
static <E> void testContain(Collection <E> c, E o) {
System.out.print("The collection " + c);
if (c.contains(o))
System.out.print(" contains");
else
System.out.print(" does not contain");
System.out.println(" the object " + o);
}
public static void main(String args[]) {
var list = new LinkedList <String>();
list.add("Petros");
list.add("Maria");
testContain(list, "Maria");
testContain(list, "John");
testContain(list, "Petros");
System.out.println("Number of elements = " + list.size());
}
}
Η διεπαφή Iterator
Η διεπαφή
υποστηρίζει τη διάσχιση και μεταβολή συλλογών.
Ορίζει τις παρακάτω μεθόδους:
- boolean hasNext()
- Επιστρέφει αληθές αν υπάρχει επόμενο στοιχείο
- Object next()
- Επιστρέφει το επόμενο στοιχείο
- void remove()
- Διαγράφει το τελευταίο στοιχείο που επιστρέφτηκε
Η διεπαφή ListIterator
Η διεπαφή ListIterator επεκτείνει την Iterator με
τις παρακάτω μεθόδους:
- boolean hasPrevious()
- Επιστρέφει αληθές αν υπάρχει προηγούμενο στοιχείο
- Object previous()
- Επιστρέφει το προηγούμενο στοιχείο
- void add(Object o)
- Προσθέτει ένα στοιχείο
- void set(Object o)
- Αντικαθιστά το τελευταίο στοιχείο που επιστρέφτηκε
Παράδειγμα της διεπαφής Iterator
import java.util.*;
public class IteratorTest {
static void fill(Collection <String> c) {
c.add("Kerkyra");
c.add("Zakynthos");
c.add("Kythira");
c.add("Santorini");
c.add("Dilos");
c.add("Samos");
c.add("Rodos");
c.add("Kastelorizo");
}
static void printAll(Collection <?> c) {
for (var i = c.iterator(); i.hasNext(); )
System.out.print(i.next() + " ");
}
public static void main(String args[]) {
var hash = new HashSet<String> ();
var list = new LinkedList<String> ();
fill(hash);
fill(list);
System.out.println("Hash contains:");
printAll(hash);
System.out.println("\nList contains:");
printAll(list);
}
}
Διάσχιση δομών με την εντολή foreach
- Μπορούμε εύκολα να διασχίσουμε τα μέλη συλλογών
που υλοποιούν τη διεπαφή Iterable μέσω της εντολής foreach.
- Η χρήση της foreach υποστηρίζεται ακόμα και για τους πίνακες
της Java.
- Η εντολή συντάσσεται ως εξής
for (Τύπος μεταβλητή : συλλογή)
εντολή
- Η μεταβλητή λαμβάνει διαδοχικά ως τιμή όλες τις τιμές της συλλογής.
Παραδείγματα foreach
Παράδειγμα διάσχισης συλλογής:
static void printAll(Collection <?> c) {
for (Object o : c)
System.out.print(o + " ");
}
Παράδειγμα διάσχισης πίνακα:
class Echo {
public static void main(String args[]) {
for (var s : args)
System.out.print(s + " ");
System.out.println();
}
}
Παράδειγμα: διάσχιση της ακολουθίας Fibonacci
import java.util.Iterator;
import java.math.BigInteger;
/**
* An Iterable interface over the Fibonacci sequence.
* @author Diomidis Spinellis
*/
class FibonacciSequence implements Iterable<BigInteger> {
/** The iterator over the Fibonacci sequence. */
private class FibonacciIterator implements Iterator<BigInteger> {
/** Integer n-2 of the series. */
private BigInteger n0 = null;
/** Integer n-1 of the series. */
private BigInteger n1 = null;
/**
* Return true.
* The FibonacciSequence sequence is infinite.
*/
public boolean hasNext() { return true; }
/** Return the next FibonacciSequence integer. */
public BigInteger next() {
if (n0 == null) {
n0 = BigInteger.ZERO;
return n0;
} else if (n1 == null) {
n1 = BigInteger.ONE;
return n1;
} else {
BigInteger r = n0.add(n1);
n0 = n1;
n1 = r;
return r;
}
}
/**
* Remove an element.
* Nothing to see here; move on.
*/
public void remove() {
throw new UnsupportedOperationException();
}
}
/** Return an iterator for the FibonacciSequence series. */
public Iterator<BigInteger> iterator() {
return new FibonacciIterator();
}
/** A simple test harness. */
public static void main(String argv[]) {
var fib = new FibonacciSequence();
for (BigInteger i : fib)
System.out.println(i);
}
}
Βλέπε και
το βίντεο για την εμφάνιση της ακολουθίας στη φύση (
http://www.youtube.com/watch?v=kkGeOWYOFoA).
Η διεπαφή Map
Η διεπαφή
ορίζει μια απεικόνιση από ένα
κλειδί (key) K σε μια
τιμή (value) V.
Η διεπαφή ορίζει μεταξύ άλλων τις παρακάτω μεθόδους:
- void clear()
- Αφαιρεί όλα τα αντικείμενα από τη συλλογή
- Object put(Object key, Object value)
- Προσθήκη στοιχείου (επιστρέφει την προηγούμενη τιμή ή null)
- void putAll(Map <? extends K, ? extends V> m)
- Προσθήκη στοιχείων
- boolean remove(Object key)
- Αφαίρεση στοιχείου (επιστρέφει την προηγούμενη τιμή ή null)
Ερωτήσεις διεπαφής Map
- V get(Object key)
- Επιστρέφει την τιμή του στοιχείου με το κλειδί key
- boolean containsKey(Object key)
- Επιστρέφει αληθές αν το στοιχείο με το κλειδί key περιέχεται
- boolean containsValue(Object value)
- Επιστρέφει αληθές αν το στοιχείο με την τιμή value περιέχεται (αργή)
- Set<K> keySet()
- Επιστρέφει το σύνολο των κλειδιών
- Collection<V> values()
- Επιστρέφει μια συλλογή με τις αποθηκευμένες τιμές
- boolean isEmpty()
- Επιστρέφει αληθές αν η συλλογή είναι άδεια
- int size()
- Επιστρέφει τον αριθμό των στοιχείων στη συλλογή
Παράδειγμα: νομισματικές ισοτιμίες
import java.util.TreeMap;
public class FXConvert {
private static TreeMap<String, Double> FXRate = new TreeMap<String, Double>();
static double FXconvert(String from, String to, double value) {
double euro = value / FXRate.get(from);
return euro * FXRate.get(to);
}
public static void main(String args[]) {
// Euro rates
FXRate.put("USD", 1.27);
FXRate.put("JPY", 126.0);
FXRate.put("GBP", 0.68);
FXRate.put("CHF", 1.57);
FXRate.put("CAD", 1.53);
FXRate.put("SEK", 9.03);
System.out.println("5 SEK = " + FXconvert("SEK", "JPY", 5) + " JPY");
System.out.println("100 GBP = " + FXconvert("GBP", "CHF", 100) + " CHF");
}
}
Η κλάση Stack
Η κλάση
υλοποιεί τη δομή δεδομένων που ονομάζεται
στοίβα (stack)
με το χαρακτηριστικό τύπο πρόσβασης
τελευταίο μέσα πρώτο έξω (last in first out) (LIFO).
H κλάση Stack υλοποιεί τη διεπαφή Collection και
ορίζει τις παρακάτω μεθόδους:
- boolean empty()
- Αληθές αν η στοίβα είναι άδεια
- E push(E item)
- Προσθέτει το αντικείμενο item στην κορυφή της στοίβας
- E pop()
- Αφαιρεί και επιστρέφει το αντικείμενο από την κορυφή της στοίβας
- E peek()
- Επιστρέφει το αντικείμενο από την κορυφή της στοίβας
οι πύργοι του Ανόι
Μπορείτε να δοκιμάστε το παιγνίδι
εδώ (
https://www.mindgames.com/game/Tower+of+Hanoi).
Παράδειγμα: οι πύργοι του Ανόι
import java.util.Stack;
import java.util.Iterator;
import java.util.Collection;
public class Hanoi {
static Stack<Integer> A, B, C;
/** Display the contents of a collection with a given name */
static <E> void showCollection(String name, Collection <E> c) {
System.out.print(name + ": ");
for (E e : c)
System.out.print(e + " ");
System.out.println();
}
/** Display the hanoi towers */
static void showConfiguration() {
showCollection("A", A);
showCollection("B", B);
showCollection("C", C);
System.out.println();
}
/** Move n blocks from to using tmp */
static <E> void move(int n, Stack<E> from, Stack<E> to, Stack<E> tmp) {
if (n == 1) {
to.push(from.pop());
showConfiguration();
} else {
move(n - 1, from, tmp, to);
to.push(from.pop());
showConfiguration();
move(n - 1, tmp, to, from);
}
}
public static void main(String args[]) {
final int N = 64;
A = new Stack<Integer>();
B = new Stack<Integer>();
C = new Stack<Integer>();
for (int i = N; i > 0; i--)
A.push(i);
showConfiguration();
move(N, A, C, B);
}
}
Άσκηση: προγραμματισμός με συμβολοσειρές και συλλογές
Άσκηση 7
Μπορείτε να κατεβάσετε το αντίστοιχο αρχείο και να στείλετε τους
βαθμούς σας από τους δεσμούς που βρίσκονται στη
σελίδα των ασκήσεων.
Βιβλιογραφία
- Rogers Candenhead. Πλήρες Εγχειρίδιο της Java 12. 8η Έκδοση.
Εκδόσεις X. Γκιούρδα, 2023.
Κεφ. 8.
- Herbert Schildt. Οδηγός της Java 7. 5η έκδοση. Εκδόσεις Γκιούρδας Μ., Αθήνα 2012. Κεφ. 5, 12, 13.
- Harvey M. Deitel και Paul J. Deitel. Java Προγραμματισμός, 6η έκδοση. Εκδόσεις Μ. Γκιούρδας, Αθήνα 2005. Κεφάλαια 17, 19, 29.
- Else Lervik και Vegard B. Havdal Java με UML. Εκδόσεις Κλειδάριθμος 2005. Κεφάλαιο 17.
- Γιάννη Κάβουρα. Προγραμματισμός με Java. Εκδόσεις Κλειθάριθμος, Αθήνα 2003. σ. 249-280, 431-468
- Γιώργος Λιακέας
Εισαγωγή στην Java. σ. 124-140 485-506,
Εκδόσεις Κλειδάριθμος 2001.
- Rogers Cadenhead και Laura Lemay Πλήρες εγχειρίδιο της Java 2 Εκδόσεις Μ. Γκιούρδας, Αθήνα 2003. σ. 211-232.
- Herbert Schildt Herb Schild's Java έτοιμες συνταγές Εκδόσεις Μ. Γκιούρδας, Αθήνα 2009. κεφ. 2, 5
- Ken Arnold and James
Gosling.
The Java
Programming Language.
Addison-Wesley, 1996.
- Steven Halim.
Visualalgo (http://visualgo.net/).
Available online http://visualgo.net/, 2011.
Submitted by Vyzantinos Repantis.
- K. N. King.
Java
Programming: from the Beginning, pages 261, 541–583.
W. W. Norton & Company, New York, NY, USA, 2000.
- Donald E. Knuth.
The Art of
Computer Programming, volume 3: Sorting and Searching.
Addison-Wesley, Reading, MA, 1973.
Περιεχόμενα