Collections
Motivation
- Massendatenverarbeitung
- Arrays nicht erweiterbar
Vererbungshierarchie

Collection<T>
public interface Collection<E> extends Iterable<E> {
int size();
boolean isEmpty();
boolean contains(Object o);
Iterator<E> iterator();
Object[] toArray();
<T> T[] toArray(T[] a);
boolean add(E e);
boolean remove(Object o);
boolean containsAll(Collection<?> c);
boolean addAll(Collection<? extends E> c);
boolean removeAll(Collection<?> c);
boolean retainAll(Collection<?> c); // getSharedElements
void clear();
boolean equals(Object o);
int hashCode();
}
boolean returnwert ⟹ hat sich Collection geändert
Konstruktoren
jede Collection hat zumindest 2 Konstruktoren:
public CollectionImpl()- erzeugt eine leere Collection
public CollectionImpl(Collection c)- erzeugt eine neue Collection, welche alle Elemente der übergebenen enthält
List<Integer> original = new ArrayList<>();
original.add(10);
original.add(20);
original.add(30);
List<Integer> copy = new ArrayList<>(original);
original.set(1, 42);
original: [10, 42, 30]
copy: [10, 20, 30]
List<E>
- Indexbasierter Zugriff
- nicht sortiert, aber sortierbar
- geordnet: Zuletzt eingefügtes Element am Ende
public interface List<E> extends Collection<E> {
E get(int index);
E set(int index, E element);
void add(int index, E element);
E remove(int index);
int indexOf(Object o);
int lastIndexOf(Object o);
ListIterator<E> listIterator();
default void sort(Comparator<? super E> c) { ... }
List<E> subList(int fromIndex, int toIndex);
}
Implementierungen
ArrayList- Liste wird durch Array realisiert.
Bei Bedarf wird das Array vergrößert LinkedList- Wie in 2.Klasse implementiert

List<String> words = new ArrayList<>();
words.add("Apfel");
words.add("Biene");
words.add("Honig");
[Apfel, Biene, Honig]
words.add(1, "Imker");
[Apfel, Imker, Biene, Honig]
for (String word : words)
word.toUpperCase();
Collections.sort(words);
words.sort(null);
[Apfel, Biene, Honig, Imker]
Set<T>
- enthält nur unique Elemente
- keine neuen Methoden
Implementierungen
HashSet- verwendet einen Hashtable; schnell
TreeSet- speichert Elemente sortiert; langsam
LinkedHashSet- verwendet zusätzlich eine
LinkedList
⟹ geordnet; mittelschnell
Collection<Integer> set = new HashSet<>();
set.add(404);
set.add(201);
set.add(-37);
set.add(-37);
[404, -37, 201]
Collection<String> set = new TreeSet<>();
set.add("POS");
set.add("AM");
set.add("NVS");
[AM, NVS, POS]
Collection<String> set = new LinkedHashSet<>();
set.add("POS");
set.add("AM");
set.add("NVS");
[POS, AM, NVS]
Problem
public class Dog {
private String name;
public Dog(String name) {
this.name = name;
}
}
Collection<Dog> dogs = new HashSet<>();
dogs.add(new Dog("Ecco"));
dogs.add(new Dog("Ecco"));
int size = dogs.size();
2
Hashing
Set<User> users = getAllUsers();
User user = new User(input);
if (users.contains(user))
...==usermuss exakt dasselbe Objekt wie im Set seinequalsUserhat 7 Instanzvariablen ⟹ langsam- Hashing
user.hashCode()wird berechnet- hat ein Element in
usersden gleichen Hashcode - könnte es das richtige sein ⟹ jetzt
equals
Kollisionen
- John Smith und Sandra Dee haben gleichen hash
- Wird nun Sandra Dee gesucht, so wird nur in Bucket 152 gesucht
Beispiel
class Student {
private int katalognummer;
private String name;
public int hashCode() {
return katalognummer;
}
}- gleiche KatNr ⟹ vielleicht gleiche Schüler
- andere KatNr ⟹ unterschiedliche Schüler
- gleiche Schüler ⟹ gleiche KatNr
- unterschiedliche Schüler ⟹
hashCode / equals - Contract
a.hashCode() == b.hashCode()- Objekte vielleicht
equal a.hashCode() != b.hashCode()- Objekte unterschiedlich
a.equals(b)a.hashCode() == b.hashCode()!a.equals(b)a != b
Mutablity
Collection<Dog> dogs = new HashSet<>();
Dog ecco = new Dog("Ecco")
dogs.add(ecco);
dogs.add(new Dog("Snoopy"));
ecco.setName("Snoopy");
⚠️ Set korrupt ⚠️
Daten in einem Set sollten immutable sein
- wie
String - Instanzvariable
private final setterreturnen neue Objekte
TreeSet<T>
public class Student {
private String name;
private int id;
public Student(String name, int id) {
this.name = name;
this.id = id;
}
}
Set<Student> students = new TreeSet<>();
Student student = new Student("Alfred", 1);
students.add(student);
java.lang.ClassCastException:
class Student cannot be cast to class java.lang.Comparable
Comparable<T>
public interface Comparable<T> {
/**
* this < o ==> < 0
* this == o ==> 0
* this > o ==> > 0
*/
public int compareTo(T o);
}
- definiert eine natural order
- beim Einfügen in ein
TreeSetgecalled - beim Sortieren einer
List/ eines Arrays gecalled
Implementierung
public class Student implements Comparable<Student>{
@Override
public int compareTo(Student o) {
int result = Integer.compare(id, o.id);
if (result != 0)
return result;
return name.compareTo(o.name);
}
Set<Student> students = new TreeSet<>();
students.add(new Student("Alfred", 1));
students.add(new Student("Bernd", 2));
students.add(new Student("Agatha", 1));
[{Agatha, id=1}, {Alfred, id=1}, {Bernd, id=2}]
public int compareTo(Student o) {
return Comparator.comparingInt(Student::getId)
.thenComparing(Student::getName)
.compare(this, o);
}
NavigableSet<T>
public interface NavigableSet<E> extends SortedSet<E> {
E lower(E e); // returnt < e
E floor(E e); // returnt <=e
E ceiling(E e); // returnt >=e
E higher(E e); // returnt > e
E pollFirst(); // return min
E pollLast(); // return max
SortedSet<E> subSet(E fromElement, E toElement); // from < all < to
SortedSet<E> headSet(E toElement); // min < all < to
SortedSet<E> tailSet(E fromElement); // from <= all < max
}
Ermöglicht äquivalent zu SQL die höchsten / niedrigsten Werte zu selektieren
Comparator<T>
public interface Comparator<T> {
/**
* o1 < o2 ==> < 0
* o1 == o2 ==> 0
* o1 > o2 ==> > 0
*/
int compare(T o1, T o2);
}
- OO - Repräsentation von Sortierregeln
- zum Überschreiben der natural Order
- oder falls keine vorhanden ist
Anwendung
List<String> caesars =
Arrays.asList("Cäsar", "Augustus", "Justinian", "Nero");
[Cäsar, Augustus, Justinian, Nero]
Collections.sort(caesars);
[Augustus, Cäsar, Justinian, Nero]
Comparator<String> byLength = new Comparator<>() {
@Override
public int compare(String o1, String o2) {
return Integer.compare(o1.length(), o2.length());
}
};
caesars.sort(byLength);
System.out.println(caesars);
[Nero, Cäsar, Augustus, Justinian]
Map / Dictionary / Assoziatives Array
🐍
dictionary = {'POS': 'SCRE', 'AM': 'RIEE', 'E': 'NEUL'}
dicionary['POS'] # -> 'SCRE'
array["POS"]
🚫 incompatible types: java.lang.String cannot be converted to int
map.put("POS", "SCRE");
map.get("POS") -> "SCRE"
Speichern von key / value - Paaren
Map<K, V>
public interface Map<K, V> {
int size();
boolean isEmpty();
boolean containsKey(Object key);
boolean containsValue(Object value);
V get(Object key);
V put(K key, V value);
V remove(Object key);
void putAll(Map<? extends K, ? extends V> m);
void clear();
Set<K> keySet();
Collection<V> values();
Set<Map.Entry<K, V>> entrySet();
default V getOrDefault(Object key, V defaultValue) { ... }
default V putIfAbsent(K key, V value) { ... }
}
Implementierungen
HashMap- Keys werden in einem
HashSetgespeichert TreeMap- Keys werden in einem
TreeSetgespeichert LinkedHashMap- Keys werden in einem
LinkedHashSetgespeichert
Iterieren
Set<K> keySet()- Liefert alle keys
Collection<V> values()- Liefert alle values
Set<Map.Entry<K, V>> entrySet()- Liefert alle key / value - Paare
Wichtige Methoden
if (map.contains(key))
result = map.get(key);
else
result = defaultValue;
return map.getOrDefault(key, defaultValue);
if (!map.contains(key))
map.put(key, newValue);
map.putIfAbsent(key, newValue);
Queue<T>
- Warteschlange, FIFO (oder FILO)
- Teilweise mit beschränkter Kapazität
public interface Queue<E> extends Collection<E> {
boolean add(E e); // full -> Exception
boolean offer(E e); // full -> false
E remove(); // empty -> Exception
E poll(); // empty -> null
E element(); // empty -> Exception
E peek(); // empty -> null
}
PriorityQueue<T>
remove/poll entfernt immer Minimum
Queue<String> queue = new PriorityQueue<>();
queue.add("NVS");
queue.add("AM");
queue.add("D");
queue.add("POS");
System.out.println(queue);
⚠️ [AM, NVS, D, POS] ⚠️
StringJoiner joined = new StringJoiner(", ");
while(!queue.isEmpty())
joined.add(queue.remove());
System.out.println(joined);
AM, D, NVS, POS