Pobieranie prezentacji. Proszę czekać

Pobieranie prezentacji. Proszę czekać

1 Kolekcje © Krzysztof Barteczko, PJWSTK 2012. 2 Pojęcie kolekcji Kolekcja jest obiektem, który grupuje elementy danych (inne obiekty) i pozwala traktować.

Podobne prezentacje


Prezentacja na temat: "1 Kolekcje © Krzysztof Barteczko, PJWSTK 2012. 2 Pojęcie kolekcji Kolekcja jest obiektem, który grupuje elementy danych (inne obiekty) i pozwala traktować."— Zapis prezentacji:

1 1 Kolekcje © Krzysztof Barteczko, PJWSTK 2012

2 2 Pojęcie kolekcji Kolekcja jest obiektem, który grupuje elementy danych (inne obiekty) i pozwala traktować je jak jeden zestaw danych, umożliwiając jednocześnie wykonywanie operacji na zestawie danych np. dodawania i usuwania oraz przeglądania elementów zestawu. Mamy do dyspozycji m.in. następujące rodzaje zestawów danych: listy (elementy mają pozycje i mogą się powtarzać) kolejki zbiory (elementy nie mają pozycji i nie mogą się powtarzać) mapy (zestaw odwzorowań klucz -> wartość) Abstrakcyjne (niezależne od sposobu realizacji) właściwości tych struktur danych opisywane są przez interfejsy, a ich konkretne realizacje przez implementacje interfejsów w klasach. Java Collections Framework: interfejsy, implementacje (klasy), algorytmy

3 3 Podstawowe interfejsy i klasy kolekcyjne Zob. bardziej szczególowo

4 4 Listy i zbiory def list = [] // ArrayList by default def set1 = new HashSet() // unsorted set def set2 = new TreeSet() // sorted set def file = new File('firms.txt') file.eachLine { list << it set1 << it set2 << it } println list println set1 println set2 Output: [IBM, Sun, Oracle, Sun, Apple] [Sun, Apple, Oracle, IBM ] [Apple, IBM, Oracle, Sun] Łatwość: - dynamiczne tablice - usuwanie duplikatów - sortowanie

5 5 Listy i zbiory = Collection Najprostsze ogólne operacje na kolekcjach: Metoda Groovy operator size() isEmpty() ref in (cond) np. if (coll)... add(Object) << += remove(Object) - clear() contains(Object) *n duplicate n times def newCol = new CollClass(oldCol) def newColl = oldColl as NewCollClass

6 6 Iterator Indeksowanie? list[7] // ok set[7] // NIE Iterator jest obiektem klasy implementującej interfejs Iterator i służy do przeglądania elementów kolekcji oraz ew. usuwania ich przy przeglądaniu Od każdej kolekcji możemy uzyskac iterator: Iterator iter = c.iterator() gdzie: c - dowolna klasa implementująca interfejs Collection. Metody: hasNext() - czy jest następny element next() - daj następny element remove() - usuń element zwrócony przez ostatnie next

7 7 Iterator - przykład def set = [1, 2, 8, 8, 17, 9] as Set println set def iter = set.iterator() while (iter.hasNext()) { elt = iter.next() println elt if (elt < 7) iter.remove() } println set Output: [17, 1, 2, 8, 9] [17, 8, 9]

8 8 "Concurrent modification" niedozwolone W trakcie iteracji za pomocą iteratora nie wolno modyfikować kolekcji innymi sposobami niż użycie metody remove() na rzecz iteratora. Niech c - dowolna kolekcja Iterator it1 = c.iterator() while (it1.hasNext()) { it1.next() l.add('x') // Błąd fazy wykonania } Iterator it1 = c.iterator(); Iterator it2 = c.iterator(); while (it1.hasNext()) { it1.next(); it2.next(); it2.remove(); // Błąd fazy wykonania } ConcurrentModificationException

9 9 Iterowanie po dowolnych kolekcjach Znane nam formy: for (var in col) ins for (Typ var : col) ins col.each { closure } col.eachWithIndex { e, i -> … } Przykład: def set = new HashSet() def list = [] for (e in ['a','b','c', 'c']) set << e set.each { list << it + 1 } println set println list Output: [b, c, a] [b1, c1, a1] Pod spodem są iteratory więc w kodzie nie można strukturalnie modyfikować kolekcji. list.each { if (it[0] == 'a') list.remove(it) } ConcurrentModificationException

10 10 Metoda collect List list = coll.collect { closure } Iterates through this collection transforming each entry into a new value using the closure as a transformer, returning a list of transformed values. def defaultBonus = 100 def f = new File('bonus.txt') println f.text def bonus = f.readLines().collect { if (it.tokenize().size() < 2) "$it $defaultBonus" else it } println 'Default bonus assigned' bonus.each { println it } Output: John 700 Steve Kate 500 Adam Default bonus assigned John 700 Steve 100 Kate 500 Adam 100

11 11 collectEntries public Map collectEntries(Closure transform) Iterates through this Collection transforming each item using the transform closure and returning a map of the resulting transformed entries. def letters = "abc" // collect letters with index using list style def n = letters.size()-1 def map = (0..n).collectEntries { ind -> [ind, letters[ind]]} println map // collect letters with index using map style map = (0..n).collectEntries { ind -> [(ind): letters[ind]] } println map

12 12 Przeszukiwanie kolekcji M.in. metody: Collection findAll(Closure closure) Finds all values matching the closure condition. Collection grep(Object filter) Iterates over every element of the collection and returns each item that matches the given filter (filter as in 'case' label of 'switch' statement) Inne metody: find { Closure } // zwraca pierwszy element spełniający warunek boolean any { Closure } // czy jest elt spełniający warunek boolean every { Closure } // czy wszystkie spełniają warunek

13 13 Przykład def allFiles = [] def dir = new File('..') dir.eachFileRecurse { if (it.isFile()) allFiles << it } def groovyFiles = allFiles.findAll { it.name.endsWith('.groovy') } def smallFiles = allFiles.grep( { it.size() < 1000 } ) def smallFileNames = smallFiles.collect { it.name } def txtFileNames = smallFileNames.grep( ~/.+\.txt/) println 'Files in dirs of ' + dir.canonicalPath println 'Is there any smaller than 100 ' + allFiles.any { it.size() < 100 } println 'Is every file older than now ' + allFiles.every { it.lastModified() < new Date().time } println 'All: ' + allFiles.size() println 'Small: ' + smallFiles.size() println 'Groovy: ' + groovyFiles.size() println 'Small text files: ' + txtFileNames.size() Output (could be): Files in dirs of E:\PJWSTK\InfSpol\Wyklady\IspWprWsp Is there any smaller than 100 true Is every file older than now true All: 1121 Small: 880 Groovy: 89 Small text files: 27

14 14 Metoda inject Z dokumentacji GDK: Object inject(Object value, Closure closure) Iterates through the given object, passing in the initial value to the closure along with the current iterated item then passing into the next iteration the value of the previous closure. def taskNr = 2 def name = "Kowalski Jan Maria" def nameWords = name.tokenize(' ') def proj = nameWords.inject("Task$taskNr") { p, elt -> p +=elt[0] } println proj Output: Task2KJM

15 15 Sumowanie Object sum() Sums the items in a collection. Objectsum(Object initialValue) Sums the items in a collection, adding the result to some initial value. Objectsum(Closure closure) Sums the result of apply a closure to each item of a collection. Object sum(Object initialValue, Closure closure) Sums the result of apply a closure to each item of a collection to sum intial value. s1 =[1, 5, 7].sum() s2 = [1, 5, 7].sum(10) s3 = new File('bonus.txt').readLines().sum { it.size() } println "$s1 $s2 $s3" Output: Z dokumentacji GDK

16 16 Operator spread i spread-dot Spread === a(*list) a(list[0], list[1],...) Spread-dot === list*.a() [list[0].a(), list[1].a()...] import static javax.swing.JOptionPane.*; def inp = showInputDialog('Enter 3 numbers') println inp if (inp) { def list = inp.tokenize() println list.sum() def nums = list*.toInteger() println nums.sum() println oper(*nums) } def oper (a, b, c) { return a * (b + c) } Output:

17 17 Listy Implementowane interfejsy: List Implementacje: ArrayList - dynamiczna tablica (szybki dostęp bezpośredni) LinkedList - lista liniowa z podwójnymi dowiązaniami (szybkie usuwanie i dodawanie w środku)

18 18 Podstawowe operacje na listach List elist = [] def list = ['A', 'B', 'C'] List list1 = new LinkedList() list3 = list1 as LinkedList list2 = list1 as ArrayList // niemożliwe przy deklaracji LinkedList list1 list.size() // == 3 list1 << 1 // list1 += 1 lub list1.add(1) - dodaje na końcu list1.add(n, 1) // dodaje w środku na pozycji n (używaj tylko dla LinkedList) Indeksowanie (np. list[100] - używaj tylko dla ArrayList) list[0] // pierwszy element list[-1] // ostatni element == list[list.size()-1] Usuwanie elementów z listy: list -= 'A' // list.remove('A') list1.remove(100) Duplikowanie listy: [1, 2] * 2 == [1, 2, 1, 2] ArrayList

19 19 Test efektywności - funkcje def randomAccess(List list) { Random rand = new Random(); times { def index = rand.nextInt(list.size()) def s = list[index] list[index] = s + 'a' } void insert(List l) { ListIterator iter = l.listIterator() // has additional methods int i = 0 while (iter.hasNext()) { iter.next(); if (i % 2) iter.add('b'); i++; } Generator liczb pseudolosowych

20 20 Efektywność test long start; def setTimer = { start = System.currentTimeMillis(); } def elapsed = { return System.currentTimeMillis() - start; } ArrayList aList = [] times() { aList << 'a' } LinkedList lList = new LinkedList(aList) // another way of converting setTimer() randomAccess(aList) println "Direct access to ArrayList: " + elapsed() + " ms" setTimer(); randomAccess(lList); println "Direct access to LinkedList: " + elapsed() + " ms" setTimer(); insert(aList); System.out.println "Inserting in ArrayList: " + elapsed() + " ms" setTimer(); insert(lList); System.out.println "Inserting in LinkedList: " + elapsed() + " ms" Output Direct access to ArrayList: 109 ms Direct access to LinkedList: 9969 ms Inserting in ArrayList: 8594 ms Inserting in LinkedList: 297 ms

21 21 Sublisty List list = ['a', 'b', 'c', 'xxxxx' ] println list.subList (1, 2) println list[1..2] println list[1..<2] // Reverting println list.reverse() println list[-1..0] Output: [b] [b, c] [b] [xxxxx, c, b, a]

22 22 Zbiory Niepowtarzające się elementy -> zasadnicza jest efektywność stwierdzania czy element jest czy nie w zbiorze. Wyszukiwanie na listach - niefektywne (metoda contains()). Dla zbiorów dwa różne podejścia: tablice mieszania - klasa HashSet, binarne drzewo do szybkiego wyszukiwania - klasa TreeSet. Uboczny efekt zastosowania TreeSet - uporządkowanie. Klasa LinkedHashSet - iteraor zwraca elementy w tej kolejności w jakiej były dodawane.

23 23 Tablice mieszania Tablica mieszania (hashtable) jest strukturą danych specjalnie przystosowaną do szybkiego odnajdywania elementów. Dla każdego elementu danych wyliczany jest kod numeryczny (liczba całkowita) nazywany kodem mieszania (hashcode), na podstawie którego obliczany jest indeks w tablicy, pod którym będzie umieszczony dany element. Może się zdarzyć, że kilka elementów otrzyma ten sam indeks, zatem elementy tablicy mieszającej stanowią listy (kubełki), na których znajdują się elementy danych o takim samym indeksie, wyliczonym na podstawie ich kodów mieszania. W Javie można wyliczyć kod mieszania dla każdego obiektu za pomocą zastosowania metody hashCode() Jeżeli prawdziwe jest a.equals(b), to musi być spełniony warunek a.hashCode() == b.hashCode().

24 24 Hashtable przykład Napisy "a", "b", "c", "d", "e", "f'", "g", "h", "i" będą umieszczone w tablicy o 7 kubełkach a kod: 97 indeks: 6 b kod: 98 indeks: 0 c kod: 99 indeks: 1 d kod: 100 indeks: 2 e kod: 101 indeks: 3 f kod: 102 indeks: 4 g kod: 103 indeks: 5 h kod: 104 indeks: 6 i kod: 105 indeks: 0 O tym czy element jest w HashSet decyduje metoda hashCode() oraz equals(Object) z klasy elementu.

25 25 Binarne wyszukiwanie Czy jest 4 w zestawie Uporządkowane: Teraz wyszukiwanie też jest szybkie. Tę ideę stosuje TreeSet.

26 26 Porównywanie obiektów Dodawanie elementów do zbiorów uporządkowanych (np. TreeSet), iterowanie po kolekcjach uporządkowanych, pobieraniee elementów z kolejek z priorytetami, a także sortowanie kolekcji i tablic algorytmami kolekcyjnymi odbywa się w oparciu o: * naturalny porządek obiektów, * lub reguły porównywania obiektów określane przez komparator - obiekt klasy implementującej interfejs Comparator.

27 27 Porządek naturalny Metoda compareTo ma następującą sygnaturę: public int compareTo(T otherObject) gdzie T jest typem obiektu, i zwraca: * liczbę < 0, jeżeli ten obiekt (this) znajduje (w porządku) przed obiektem otherObject, * liczbę > 0, jeżeli ten obiekt (this) znajduje (w porządku) po obiekcie otherObject, * 0, jeśli obiekty są takie same.

28 28 Komparator Komparator jest obiektem porównującym inne obiekty Komparatory są realizowane jako obiekty klas implementujących interfejs Comparator, gdzie T jest typem porównywanych obiektów Interfejs ten zawiera ważną metodę: int compare(T o1, T o2) W Groovy interfejsy z metodą compare imlementujemy tak: def comp = [ compare: { o1, o2 ->... } ] as Comparator Closure Powstaje obiekt-komparator Nazwa metody

29 29 TreeSet - przykład def byNames = new TreeSet() // naturalny porządek def sizeComp = [compare: { a, b -> a.size().compareTo(b.size()) } ] as Comparator def bySize = new TreeSet(sizeComp) // porządek komparatora new File('.').eachFileRecurse { if (it.isFile() && it.name.endsWith('.groovy')) { byNames << it.name bySize << it } println byNames println bySize*.getName() Output: [ArrIntro.groovy, ArrListConv.groovy, Collect1.groovy, Inject.groovy,... ] [ListConv.groovy, Summing.groovy, ArrListConv.groovy, Inject.groovy,... ]

30 30 Algorytmy kolekcyjne Dla każdej kolekcji i tablicy sort, max, min - bez arg (naturalny porządek) z 1 arg (obiekt komparator lub Closure jako komparator) def list = [ "Red", 'Green', 'Blue' ] println list.sort() println list.sort { o1, o2 -> o1.size() - o2.size() } Output: [Blue, Green, Red] [Red, Blue, Green]

31 31 Mapy Mapa jest jednoznacznym odwzorowaniem zbioru kluczy w zbiór wartości. kolekcja par: klucz - wartość, która zapewniają odnajdywanie wartości związanej z podanym kluczem. Np. zestaw danych, który zawiera nazwiska i numery telefonów i pozwala na odnajdywanie numeru telefonu (poszukiwanej wartości) po nazwisku (kluczu). Zarówno klucze, jak i wartości mogą być referencjami do dowolnych obiektów (jak również wartościami null). Wartości kluczy nie mogą się powtarzać (odwzorowanie musi być jednoznaczne). Natomiast pod różnymi kluczami można zapisać te same wartości (odzworowanie nie musi być wzajemnie jednoznaczne).

32 32 Rodzaje map Hierarchia: HashMap - klucze to HashSet TreeMap - klucze to TreeMap LinkedHashMap - klucze w kolejnosci w jakiej były dodawane

33 33 Proste operacje Tworzenie w programie: map1 = [:] // pusta mapa map2 = [ Joan: ' ', Steve: ' '] Dostęp: map2.Joan // map2['Joan'] // map2.Dave // null name = 'Steve' map2[name] // map1['x'] = 7 map1.y = 23 map1.x + map1.y // 30 Takie mapy są typu: Map i LinkedHasMap

34 34 Metody interfejsu Map void clear() Removes all of the mappings from this map (optional operation). boolean containsKey(Object key) Returns true if this map contains a mapping for the specified key. boolean containsValue(Object value) Returns true if this map maps one or more keys to the specified value. Set > entrySet() Returns a Set view of the mappings contained in this map. V get(Object key) Returns the value to which the specified key is mapped, or null if this map contains no mapping for the key. Boolean isEmpty() Returns true if this map contains no key-value mappings. Set keySet() Returns a Set view of the keys contained in this map. V put(K key, V value) Associates the specified value with the specified key in this map (optional operation). void putAll(Map m) Copies all of the mappings from the specified map to this map (optional operation). V remove(Object key) Removes the mapping for a key from this map if it is present (optional operation). Int size() Returns the number of key-value mappings in this map. Collection values() Returns a Collection view of the values contained in this map.

35 35 Przeglądanie map map.each { e -> // e.key == klucz, e.value == value } map.each { key, val ->... } map.eachWithIndex { e, i ->... } lub {k, v, i ->...} for (key in map.keySet) ins for (Type key : map.keySet() ins for (Map.Entry e : map.entrySet()) ins

36 36 Wyszukiwanie w mapach Dostępne metody: findAll { e ->... } lub findAll { key, value ->... } Tak samo find, every, any...

37 37 Przykład: zliczanie słów w pliku File file = new File('src/SearchingCol.groovy') def wmap = [:] as TreeMap file.eachLine { line -> line.tokenize(' \t+=*/~\\\'"[]{}(),;,.?:').each { def num = wmap.get( it, 0) // default value supplied (Groovy) wmap[it] = num + 1 } wmap.each { println it.key + ' ' + it.value } Output (could be):... allFiles 7 any 2 canonicalPath 1 collect 1 def 6...

38 38 Tablice Tablice są zestawami elementów (wartości) tego samego typu, ułożonych na określonych pozycjach. Do każdego z tych elementów mamy bezpośredni ( swobodny - nie wymagający przeglądania innych elementów zestawu) dostęp poprzez nazwę tablicy i pozycję elementu w zestawie, określaną przez indeks lub indeksy tablicy. Różnica pomiędzy tablicami a prostymi listami: > rozmiar tablicy niezmienny (po utworzeniu), > rozmiar listy może się zmieniać (dodawanie i usuwanie elementów) Tablice - po co ? efektywność wiele metod z klas Javy zwraca tablice, lub wymaga arg. tablic niemodyfikowalna (co do rozmiaru) lista

39 39 Definiowanie i tworzenie tablic Tworzenie tablicy: new T[n] gdzie: * T - typ elementów tablicy * n - rozmiar tablicy (liczba elementów tablicy) Np. arr = new BigDecimal[5] def arr1 //... arr1 = new Integer[3] // można też użyć typu int // n jest typu Integer i ma wartość (np. wprowadzoną) def arr2 = new String[n] int[] a1 a1 = new int[10] String[] stab = new String[n] Tablica jest obiektem typu T[], tu: int[] i String[]

40 40 Dostęp do elementów tablic indeksy - liczby całkowite typu int od 0 liczba elementów w tablicy: n = arr.length // Groovy i Java n = arr.size() // Groovy dostęp do elementów: arr[0], arr[1],..., arr[n-1] np.: def arr = new int[3] arr[0] = 1 arr[1] = 2 arr[2] = 3 s = arr[1] + arr[2] arr[0] = arr[0] * 2

41 41 Tablice a proste listy - przykład def arr = new String[2] arr[0] = 'a' arr[1] = 'b' //arr << 'c' błąd - operator << nie dla tablic //arr[2]='c' ArrayIndexOutOfBoundsException println arr.class.name + ' ' + arr println 'First: ' + arr[0] println 'Last: ' + arr[arr.length-1] println 'Last: ' + arr[arr.size()-1] println 'Last: ' + arr[-1] def list = [] list[0] = 'a' list[1] = 'b' list[2] = 'c' println list.class.name + ' ' + list println 'First: ' + list[0] println 'Last: ' + list[list.size()-1] //println 'Last: ' + list[list.length-1] błąd length nie dla list println 'Last: ' + list[-1] println list list << 'c' println list Output: [Ljava.lang.String; [a, b] First: a Last: b java.util.ArrayList [a, b, c] First: a Last: c [a, b, c] [a, b, c, c]

42 42 Konwersje lista tablica Tablice można przekształcać w listy i vice versa: arr = [1, 2, 3] as Integer[] // można też as int[] list = [ 'a', 'b', 'c' ] arr = list as String[] // można też: arr = (String[]) list list = arr as List // ten sam efekt co arr as ArrayList list = arr.toList() // j.w.

43 43 Tablice i listy - identyczne operowanie Większość omówionych sposobów dostępu, iterowanie, przeszukiwania itp. może być używana jednolicie dla tablic i list. def list = [1, 7, 15, 22 ] def arr = [1, 2, 11, 17] as int[] println list.class.name + ' ' + arr.class.name sameSyntax list sameSyntax arr def sameSyntax(obj) { obj.each { print it + ' ' } println() println obj.findAll { it > 10 } println obj.inject(0) { sum, elt -> sum += elt } } Output: java.util.ArrayList [I [15, 22] [11, 17] 31


Pobierz ppt "1 Kolekcje © Krzysztof Barteczko, PJWSTK 2012. 2 Pojęcie kolekcji Kolekcja jest obiektem, który grupuje elementy danych (inne obiekty) i pozwala traktować."

Podobne prezentacje


Reklamy Google