{"id":2573,"date":"2021-04-22T16:20:22","date_gmt":"2021-04-22T14:20:22","guid":{"rendered":"https:\/\/www.kompikownia.pl\/?p=2573"},"modified":"2021-04-22T16:27:55","modified_gmt":"2021-04-22T14:27:55","slug":"java-internals-jak-dziala-arraylist-jezyku-java","status":"publish","type":"post","link":"https:\/\/www.kompikownia.pl\/index.php\/2021\/04\/22\/java-internals-jak-dziala-arraylist-jezyku-java\/","title":{"rendered":"Java Internals: Jak dzia\u0142a ArrayList j\u0119zyku Java?"},"content":{"rendered":"<span class=\"rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">Czas czytania:<\/span> <span class=\"rt-time\">3<\/span> <span class=\"rt-label rt-postfix\">minut<\/span><\/span>\n<p>Programuj\u0105c w j\u0119zyku Java, z pewno\u015bci\u0105 wielokrotnie korzysta\u0142e\u015b z r\u00f3\u017cnego rodzaju list (ArrayList, LinkedList itd). Ale czy zastanawia\u0142e\u015b si\u0119 kiedy\u015b, jak wygl\u0105da ich wewn\u0119trzna implementacja? Analizowa\u0142e\u015b, jak wp\u0142ywa ona na przyk\u0142ad na wydajno\u015b\u0107 twojego programu oraz zajmowan\u0105 przeze\u0144 pami\u0119\u0107? W tym artykule zajmiemy si\u0119 analiz\u0105 wewn\u0119trznej implementacji ArrayList, bazuj\u0105c na implementacji openjdk-11 <a href=\"https:\/\/github.com\/AdoptOpenJDK\/openjdk-jdk11\/blob\/master\/src\/java.base\/share\/classes\/java\/util\/ArrayList.java\" data-type=\"URL\" data-id=\"https:\/\/github.com\/AdoptOpenJDK\/openjdk-jdk11\/blob\/master\/src\/java.base\/share\/classes\/java\/util\/ArrayList.java\" target=\"_blank\" rel=\"noreferrer noopener\">[4]<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Czym jest ArrayList?<\/h2>\n\n\n\n<p>ArrayList jest tablic\u0105, kt\u00f3rej rozmiar mo\u017cna dynamicznie zmienia\u0107. W przeciwie\u0144stwie do zwyk\u0142ych tablic, kt\u00f3re maj\u0105 sta\u0142y rozmiar, ArrayList ro\u015bnie dynamicznie w miar\u0119 jak dodajemy do niej nowe elementy.<\/p>\n\n\n\n<p>Na pocz\u0105tku przyjrzyjmy si\u0119 definicji ArrayList. <\/p>\n\n\n<div class=\"codecolorer-container java default\" style=\"overflow:auto;white-space:nowrap;width:100%;\"><div class=\"java codecolorer\"><span class=\"kw1\">public<\/span> <span class=\"kw1\">class<\/span> ArrayList<span class=\"sy0\">&lt;<\/span>E<span class=\"sy0\">&gt;<\/span> <span class=\"kw1\">extends<\/span> AbstractList<span class=\"sy0\">&lt;<\/span>E<span class=\"sy0\">&gt;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">implements<\/span> List<span class=\"sy0\">&lt;<\/span>E<span class=\"sy0\">&gt;<\/span>, RandomAccess, <a href=\"http:\/\/www.google.com\/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+cloneable\"><span class=\"kw3\">Cloneable<\/span><\/a>, java.<span class=\"me1\">io<\/span>.<a href=\"http:\/\/www.google.com\/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+serializable\"><span class=\"kw3\">Serializable<\/span><\/a><\/div><\/div>\n\n\n\n<p class=\"example_code\">ArrayList rozszerza klas\u0119 <em>AbstractList&lt;E&gt;<\/em>. Klasa ta jest &#8222;szkieletem&#8221; dla implementacji interfejsu List&lt;E&gt;. AbstractList&lt;E&gt; dostarcza implementacji &#8222;uniwersalnych&#8221; metod, jak &#8222;lastIndexOf&#8221;, &#8222;addAll&#8221; itd. kt\u00f3rych mechanizm dzia\u0142ania nie zale\u017cy od konkretnej implementacji listy.  <\/p>\n\n\n\n<p class=\"example_code\">Interfejs znacznikowy <em>RandomAccess<\/em> <a rel=\"noreferrer noopener\" href=\"https:\/\/docs.oracle.com\/javase\/7\/docs\/api\/java\/util\/RandomAccess.html\" data-type=\"URL\" data-id=\"https:\/\/docs.oracle.com\/javase\/7\/docs\/api\/java\/util\/RandomAccess.html\" target=\"_blank\">[1]<\/a> u\u017cywany jest do oznaczenia klas, w kt\u00f3rych dost\u0119p do poszczeg\u00f3lnych element\u00f3w listy jest bardzo szybki. ArrayList spe\u0142nia ten warunek. Dost\u0119p do dowolnego elementu listy uzyskamy w czasie O(1). (Nie ma znaczenia, czy jest to element pierwszy, drugi, setny czy milionowy). <\/p>\n\n\n\n<p class=\"example_code\">Interfejs znacznikowy <em>Cloneable <\/em>zapewnia, \u017ce obiekt klasy mo\u017cna sklonowa\u0107. B\u0119dzie to tzw. &#8222;deep copy&#8221;<strong> <\/strong>(g\u0142\u0119boka kopia). Oznacza to, \u017ce po wywo\u0142aniu metody <em>clone <\/em>skopiowane do nowego obiektu zostan\u0105 nie referencje, a zawarto\u015b\u0107 wszystkich element\u00f3w istniej\u0105cych w obiekcie. <\/p>\n\n\n\n<p class=\"example_code\">Interfejs znacznikowy <em>Serializable <\/em>m\u00f3wi, \u017ce klasa jest serializowalna. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Prywatne statyczne elementy klasy ArrayList<\/h2>\n\n\n\n<p>Przyjrzyjmy si\u0119 nast\u0119puj\u0105cemu fragmentowi implementacji klasy ArrayList.<\/p>\n\n\n<div class=\"codecolorer-container java default\" style=\"overflow:auto;white-space:nowrap;width:100%;height:100%;\"><table cellspacing=\"0\" cellpadding=\"0\"><tbody><tr><td class=\"line-numbers\"><div>111<br \/>112<br \/>113<br \/>114<br \/>115<br \/>116<br \/>117<br \/>118<br \/>119<br \/>120<br \/>121<br \/>122<br \/>123<br \/>124<br \/>125<br \/>126<br \/>127<br \/>128<br \/>129<br \/>130<br \/>131<br \/>132<br \/>133<br \/>134<br \/>135<br \/>136<br \/>137<br \/>138<br \/><\/div><\/td><td><div class=\"java codecolorer\">&nbsp; <span class=\"kw1\">private<\/span> <span class=\"kw1\">static<\/span> <span class=\"kw1\">final<\/span> <span class=\"kw4\">int<\/span> DEFAULT_CAPACITY <span class=\"sy0\">=<\/span> <span class=\"nu0\">10<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; <span class=\"co3\">\/**<br \/>\n&nbsp; &nbsp; &nbsp;* Shared empty array instance used for empty instances.<br \/>\n&nbsp; &nbsp; &nbsp;*\/<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">private<\/span> <span class=\"kw1\">static<\/span> <span class=\"kw1\">final<\/span> <a href=\"http:\/\/www.google.com\/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+object\"><span class=\"kw3\">Object<\/span><\/a><span class=\"br0\">&#91;<\/span><span class=\"br0\">&#93;<\/span> EMPTY_ELEMENTDATA <span class=\"sy0\">=<\/span> <span class=\"br0\">&#123;<\/span><span class=\"br0\">&#125;<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; <span class=\"co3\">\/**<br \/>\n&nbsp; &nbsp; &nbsp;* Shared empty array instance used for default sized empty instances. We<br \/>\n&nbsp; &nbsp; &nbsp;* distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when<br \/>\n&nbsp; &nbsp; &nbsp;* first element is added.<br \/>\n&nbsp; &nbsp; &nbsp;*\/<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">private<\/span> <span class=\"kw1\">static<\/span> <span class=\"kw1\">final<\/span> <a href=\"http:\/\/www.google.com\/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+object\"><span class=\"kw3\">Object<\/span><\/a><span class=\"br0\">&#91;<\/span><span class=\"br0\">&#93;<\/span> DEFAULTCAPACITY_EMPTY_ELEMENTDATA <span class=\"sy0\">=<\/span> <span class=\"br0\">&#123;<\/span><span class=\"br0\">&#125;<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; <span class=\"co3\">\/**<br \/>\n&nbsp; &nbsp; &nbsp;* The array buffer into which the elements of the ArrayList are stored.<br \/>\n&nbsp; &nbsp; &nbsp;* The capacity of the ArrayList is the length of this array buffer. Any<br \/>\n&nbsp; &nbsp; &nbsp;* empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA<br \/>\n&nbsp; &nbsp; &nbsp;* will be expanded to DEFAULT_CAPACITY when the first element is added.<br \/>\n&nbsp; &nbsp; &nbsp;*\/<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">transient<\/span> <a href=\"http:\/\/www.google.com\/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+object\"><span class=\"kw3\">Object<\/span><\/a><span class=\"br0\">&#91;<\/span><span class=\"br0\">&#93;<\/span> elementData<span class=\"sy0\">;<\/span> <span class=\"co1\">\/\/ non-private to simplify nested class access<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; <span class=\"co3\">\/**<br \/>\n&nbsp; &nbsp; &nbsp;* The size of the ArrayList (the number of elements it contains).<br \/>\n&nbsp; &nbsp; &nbsp;*<br \/>\n&nbsp; &nbsp; &nbsp;* @serial<br \/>\n&nbsp; &nbsp; &nbsp;*\/<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">private<\/span> <span class=\"kw4\">int<\/span> size<span class=\"sy0\">;<\/span><\/div><\/td><\/tr><\/tbody><\/table><\/div>\n\n\n\n<p>Ju\u017c na podstawie tego fragmentu i deklaracji kilku prywatnych element\u00f3w klasy ArrayList mo\u017cemy domy\u015bli\u0107 si\u0119, w jakiej strukturze elementy wewn\u0105trz niej s\u0105 przechowywane. <strong>Jest to oczywi\u015bcie zwyk\u0142a tablica obiekt\u00f3w Object[]<\/strong>. Jej deklaracj\u0119 widzimy w linijce 131 na powy\u017cszym listingu. Zastosowanie wyja\u015bnia zreszt\u0105 komentarz umieszczony w kodzie \u017ar\u00f3d\u0142owym. <\/p>\n\n\n\n<p class=\"example_code\">Domy\u015blny rozmiar pustej ArrayListy sugeruje zmienna <em>DEFAULT_CAPACITY<\/em> znajduj\u0105ca si\u0119 w linijce 111. Wynosi ona 10 element\u00f3w. Ale czy faktycznie dla pustej ArrayListy wewn\u0119trzna tablica obiekt\u00f3w ma rozmiar 10? W\u0105tpliwo\u015bci rozbudzaj\u0105 zmienne <em>EMPTY_ELEMENTDATA<\/em> i <em>DEFAULTCAPACITY_EMPTY_ELEMENTDATA<\/em>. Wielko\u015b\u0107 tych tablic wynosi 0. Aby rozwia\u0107 nasze w\u0105tpliwo\u015bci, zerknijmy na kod \u017ar\u00f3d\u0142owy konstruktor\u00f3w ArrayListy.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Konstruktory klasy ArrayList<\/h2>\n\n\n<div class=\"codecolorer-container java default\" style=\"overflow:auto;white-space:nowrap;width:100%;\"><table cellspacing=\"0\" cellpadding=\"0\"><tbody><tr><td class=\"line-numbers\"><div>145<br \/>146<br \/>147<br \/>148<br \/>149<br \/>150<br \/>151<br \/>152<br \/>153<br \/>154<br \/>155<br \/>156<br \/>157<br \/>158<br \/>159<br \/>160<br \/>161<br \/><\/div><\/td><td><div class=\"java codecolorer\">&nbsp; &nbsp; <span class=\"co3\">\/**<br \/>\n&nbsp; &nbsp; &nbsp;* Constructs an empty list with the specified initial capacity.<br \/>\n&nbsp; &nbsp; &nbsp;*<br \/>\n&nbsp; &nbsp; &nbsp;* @param &nbsp;initialCapacity &nbsp;the initial capacity of the list<br \/>\n&nbsp; &nbsp; &nbsp;* @throws IllegalArgumentException if the specified initial capacity<br \/>\n&nbsp; &nbsp; &nbsp;* &nbsp; &nbsp; &nbsp; &nbsp; is negative<br \/>\n&nbsp; &nbsp; &nbsp;*\/<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">public<\/span> <a href=\"http:\/\/www.google.com\/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+arraylist\"><span class=\"kw3\">ArrayList<\/span><\/a><span class=\"br0\">&#40;<\/span><span class=\"kw4\">int<\/span> initialCapacity<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>initialCapacity<span class=\"sy0\">&gt;<\/span><span class=\"nu0\">0<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">this<\/span>.<span class=\"me1\">elementData<\/span> <span class=\"sy0\">=<\/span> <span class=\"kw1\">new<\/span> <a href=\"http:\/\/www.google.com\/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+object\"><span class=\"kw3\">Object<\/span><\/a><span class=\"br0\">&#91;<\/span>initialCapacity<span class=\"br0\">&#93;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span> <span class=\"kw1\">else<\/span> <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>initialCapacity <span class=\"sy0\">==<\/span> <span class=\"nu0\">0<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">this<\/span>.<span class=\"me1\">elementData<\/span> <span class=\"sy0\">=<\/span> EMPTY_ELEMENTDATA<span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span> <span class=\"kw1\">else<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">throw<\/span> <span class=\"kw1\">new<\/span> <a href=\"http:\/\/www.google.com\/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+illegalargumentexception\"><span class=\"kw3\">IllegalArgumentException<\/span><\/a><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;Illegal Capacity: &quot;<\/span><span class=\"sy0\">+<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;initialCapacity<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><\/div><\/td><\/tr><\/tbody><\/table><\/div>\n\n\n\n<p class=\"example_code\">Pierwszy z trzech konstruktor\u00f3w pozwala na stworzenie ArrayListy o okre\u015blonej pocz\u0105tkowej pojemno\u015bci. Taki konstruktor tworzy tablic\u0119 elementData o wielko\u015bci przekazanej w konstruktorze (je\u015bli ta wielko\u015b\u0107 jest wi\u0119ksza od zera). Je\u015bli <em>initialCapacity<\/em> wynosi 0, rozmiar tablicy domy\u015blnie wynosi 0. Przy dodawaniu kolejnych element\u00f3w b\u0119dzie on zwi\u0119kszany. A jak? Om\u00f3wimy to sobie za chwil\u0119. <\/p>\n\n\n<div class=\"codecolorer-container java default\" style=\"overflow:auto;white-space:nowrap;width:100%;\"><table cellspacing=\"0\" cellpadding=\"0\"><tbody><tr><td class=\"line-numbers\"><div>163<br \/>164<br \/>165<br \/>166<br \/>167<br \/>168<br \/><\/div><\/td><td><div class=\"java codecolorer\">&nbsp; <span class=\"co3\">\/**<br \/>\n&nbsp; &nbsp; &nbsp;* Constructs an empty list with an initial capacity of ten.<br \/>\n&nbsp; &nbsp; &nbsp;*\/<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">public<\/span> <a href=\"http:\/\/www.google.com\/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+arraylist\"><span class=\"kw3\">ArrayList<\/span><\/a><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">this<\/span>.<span class=\"me1\">elementData<\/span> <span class=\"sy0\">=<\/span> DEFAULTCAPACITY_EMPTY_ELEMENTDATA<span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><\/div><\/td><\/tr><\/tbody><\/table><\/div>\n\n\n\n<p>W konstruktorze bezparametrowym nie ma wielkiej filozofii. Domy\u015blny rozmiar wynosi 0, a ArrayLista jest pusta. <\/p>\n\n\n\n<p class=\"example_code\"><strong>Zagadka: <\/strong>Czy polecenia <em>new ArrayList&lt;&gt;(0)<\/em> i <em>new ArrayList&lt;&gt;()<\/em> po dodaniu pierwszego elementu utworz\u0105 wewn\u0119trznie tablic\u0119 o tym samym rozmiarze? Zastan\u00f3w si\u0119 nad tym zanim przejdziesz do dalszej cz\u0119\u015bci tekstu. Zwr\u00f3\u0107 uwag\u0119 na to, \u017ce tw\u00f3rcy implementacji rozr\u00f3\u017cnili te dwie sytuacje za pomoc\u0105 inicjacji ArrayListy dwoma r\u00f3\u017cnymi obiektami: albo za pomoc\u0105 <em>DEFAULTCAPACITY_EMPTY_ELEMENTDATA<\/em> albo <em>EMPTY_ELEMENTDATA<\/em>.<\/p>\n\n\n\n\n<div class=\"codecolorer-container java default\" style=\"overflow:auto;white-space:nowrap;width:100%;height:100%;\"><table cellspacing=\"0\" cellpadding=\"0\"><tbody><tr><td class=\"line-numbers\"><div>170<br \/>171<br \/>172<br \/>173<br \/>174<br \/>175<br \/>176<br \/>177<br \/>178<br \/>179<br \/>180<br \/>181<br \/>182<br \/>183<br \/>184<br \/>185<br \/>186<br \/>187<br \/>188<br \/>189<br \/>190<br \/><\/div><\/td><td><div class=\"java codecolorer\">&nbsp; &nbsp; <span class=\"co3\">\/**<br \/>\n&nbsp; &nbsp; &nbsp;* Constructs a list containing the elements of the specified<br \/>\n&nbsp; &nbsp; &nbsp;* collection, in the order they are returned by the collection's<br \/>\n&nbsp; &nbsp; &nbsp;* iterator.<br \/>\n&nbsp; &nbsp; &nbsp;*<br \/>\n&nbsp; &nbsp; &nbsp;* @param c the collection whose elements are to be placed into this list<br \/>\n&nbsp; &nbsp; &nbsp;* @throws NullPointerException if the specified collection is null<br \/>\n&nbsp; &nbsp; &nbsp;*\/<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">public<\/span> <a href=\"http:\/\/www.google.com\/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+arraylist\"><span class=\"kw3\">ArrayList<\/span><\/a><span class=\"br0\">&#40;<\/span>Collection<span class=\"sy0\">&lt;?<\/span> <span class=\"kw1\">extends<\/span> E<span class=\"sy0\">&gt;<\/span> c<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <a href=\"http:\/\/www.google.com\/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+object\"><span class=\"kw3\">Object<\/span><\/a><span class=\"br0\">&#91;<\/span><span class=\"br0\">&#93;<\/span> a <span class=\"sy0\">=<\/span> c.<span class=\"me1\">toArray<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span><span class=\"br0\">&#40;<\/span>size <span class=\"sy0\">=<\/span> a.<span class=\"me1\">length<\/span><span class=\"br0\">&#41;<\/span> <span class=\"sy0\">!=<\/span> <span class=\"nu0\">0<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>c.<span class=\"me1\">getClass<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"sy0\">==<\/span> <a href=\"http:\/\/www.google.com\/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+arraylist\"><span class=\"kw3\">ArrayList<\/span><\/a>.<span class=\"kw1\">class<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; elementData <span class=\"sy0\">=<\/span> a<span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span> <span class=\"kw1\">else<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; elementData <span class=\"sy0\">=<\/span> <a href=\"http:\/\/www.google.com\/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+arrays\"><span class=\"kw3\">Arrays<\/span><\/a>.<span class=\"me1\">copyOf<\/span><span class=\"br0\">&#40;<\/span>a, size, <a href=\"http:\/\/www.google.com\/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+object\"><span class=\"kw3\">Object<\/span><\/a><span class=\"br0\">&#91;<\/span><span class=\"br0\">&#93;<\/span>.<span class=\"kw1\">class<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span> <span class=\"kw1\">else<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"co1\">\/\/ replace with empty array.<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; elementData <span class=\"sy0\">=<\/span> EMPTY_ELEMENTDATA<span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><\/div><\/td><\/tr><\/tbody><\/table><\/div>\n\n\n\n\n<p>Przyjrzyjmy si\u0119 ostatniemu konstruktorowi. Tworzy on kopi\u0119 ArrayListy na podstawie kolekcji zawartej w argumencie konstruktora. <\/p>\n\n\n\n<p>Na pocz\u0105tku kolekcja konwertowana jest do tablicy obiekt\u00f3w. Uzyskana tablica jest przypisywana do wewn\u0119trznej ArrayListowej tablicy elementData. Je\u015bli \u017ar\u00f3d\u0142owa kolekcja jest pusta, konstruktor zachowa si\u0119 tak samo jak wywo\u0142anie new ArrayList&lt;&gt;(0); <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Dodawanie i usuwanie element\u00f3w ArrayList<\/h2>\n\n\n\n<p>Skoro wiemy, w jaki spos\u00f3b obiekt ArrayList jest konstruowany, pora zastanowi\u0107 si\u0119 jak dzia\u0142a operacja dodawania i usuwania element\u00f3w. Zanim przejdziemy do analizy kodu zastan\u00f3wmy si\u0119 jak by to mog\u0142o dzia\u0142a\u0107 &#8211; na logik\u0119. Musimy posiada\u0107 wska\u017anik, kt\u00f3ry m\u00f3wi nam jaki jest aktualny rozmiar tablicy. Je\u015bli ten wska\u017anik jest mniejszy od rozmiaru tablicy &#8211; sytuacja jest prosta. Zapisujemy wtedy dodawany element w kolejnej kom\u00f3rce tablicy. Je\u015bli tak nie jest &#8211; trzeba w jaki\u015b spos\u00f3b zwi\u0119kszy\u0107 rozmiar tablicy. Jak to zrobili tw\u00f3rcy implementacji openjdk? Zobaczmy. <\/p>\n\n\n<div class=\"codecolorer-container java default\" style=\"overflow:auto;white-space:nowrap;width:100%;\"><table cellspacing=\"0\" cellpadding=\"0\"><tbody><tr><td class=\"line-numbers\"><div>503<br \/>504<br \/>505<br \/>506<br \/>507<br \/>508<br \/>509<br \/>510<br \/>511<br \/>512<br \/>513<br \/><\/div><\/td><td><div class=\"java codecolorer\">&nbsp; &nbsp; &nbsp;<span class=\"co3\">\/**<br \/>\n&nbsp; &nbsp; &nbsp;* Appends the specified element to the end of this list.<br \/>\n&nbsp; &nbsp; &nbsp;*<br \/>\n&nbsp; &nbsp; &nbsp;* @param e element to be appended to this list<br \/>\n&nbsp; &nbsp; &nbsp;* @return {@code true} (as specified by {@link Collection#add})<br \/>\n&nbsp; &nbsp; &nbsp;*\/<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">public<\/span> <span class=\"kw4\">boolean<\/span> add<span class=\"br0\">&#40;<\/span>E e<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; modCount<span class=\"sy0\">++;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; add<span class=\"br0\">&#40;<\/span>e, elementData, size<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">return<\/span> <span class=\"kw2\">true<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><\/div><\/td><\/tr><\/tbody><\/table><\/div>\n\n\n\n<p class=\"example_code\">Publiczna metoda <em>add<\/em> nie jest d\u0142uga. Zawiera tylko trzy linijki :). <em>modCount<\/em> jest polem zadeklarowanym w klasie <em>AbstractList.<\/em> Przekazuje ono informacj\u0119 o tym, ile razy lista by\u0142a modyfikowana. Nast\u0119pna linijka to wywo\u0142anie prywatnej metody <em>add<\/em>. Przyjrzyjmy si\u0119 jej implementacji.<\/p>\n\n\n<div class=\"codecolorer-container java default\" style=\"overflow:auto;white-space:nowrap;width:100%;\"><table cellspacing=\"0\" cellpadding=\"0\"><tbody><tr><td class=\"line-numbers\"><div>479<br \/>480<br \/>481<br \/>482<br \/>483<br \/>484<br \/>485<br \/>486<br \/>487<br \/>488<br \/>489<br \/><\/div><\/td><td><div class=\"java codecolorer\">&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"co3\">\/**<br \/>\n&nbsp; &nbsp; &nbsp;* This helper method split out from add(E) to keep method<br \/>\n&nbsp; &nbsp; &nbsp;* bytecode size under 35 (the -XX:MaxInlineSize default value),<br \/>\n&nbsp; &nbsp; &nbsp;* which helps when add(E) is called in a C1-compiled loop.<br \/>\n&nbsp; &nbsp; &nbsp;*\/<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">private<\/span> <span class=\"kw4\">void<\/span> add<span class=\"br0\">&#40;<\/span>E e, <a href=\"http:\/\/www.google.com\/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+object\"><span class=\"kw3\">Object<\/span><\/a><span class=\"br0\">&#91;<\/span><span class=\"br0\">&#93;<\/span> elementData, <span class=\"kw4\">int<\/span> s<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>s <span class=\"sy0\">==<\/span> elementData.<span class=\"me1\">length<\/span><span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; elementData <span class=\"sy0\">=<\/span> grow<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; elementData<span class=\"br0\">&#91;<\/span>s<span class=\"br0\">&#93;<\/span> <span class=\"sy0\">=<\/span> e<span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; size <span class=\"sy0\">=<\/span> s <span class=\"sy0\">+<\/span> <span class=\"nu0\">1<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><\/div><\/td><\/tr><\/tbody><\/table><\/div>\n\n\n\n<p class=\"example_code\">Zachowanie metody zgadza si\u0119 z naszymi przewidywaniami. Argument <em>s<\/em> jest aktualnym rozmiarem tablicy (je\u015bli nie wiesz dlaczego &#8211; zwr\u00f3\u0107 uwag\u0119 na poprzedni listing i wywo\u0142anie metody <em>add<\/em>). Je\u015bli aktualny rozmiar tablicy jest mniejszy od rozmiaru ca\u0142kowitego &#8211; sytuacja jest prosta. Nowy element zapisujemy na kolejnej pozycji tablicy. Je\u015bli natomiast przekroczyliby\u015bmy jej rozmiar &#8211; musimy powi\u0119kszy\u0107 tablic\u0119 <em>elementData.<\/em><\/p>\n\n\n<div class=\"codecolorer-container java default\" style=\"overflow:auto;white-space:nowrap;width:100%;height:100%;\"><table cellspacing=\"0\" cellpadding=\"0\"><tbody><tr><td class=\"line-numbers\"><div>240<br \/>241<br \/>242<br \/>243<br \/>244<br \/>245<br \/>246<br \/>247<br \/>248<br \/>249<br \/>250<br \/>251<br \/>252<br \/>253<br \/>254<br \/>255<br \/>256<br \/>257<br \/>258<br \/>259<br \/>260<br \/>261<br \/>262<br \/><\/div><\/td><td><div class=\"java codecolorer\">&nbsp; &nbsp; <span class=\"kw1\">private<\/span> <a href=\"http:\/\/www.google.com\/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+object\"><span class=\"kw3\">Object<\/span><\/a><span class=\"br0\">&#91;<\/span><span class=\"br0\">&#93;<\/span> grow<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">return<\/span> grow<span class=\"br0\">&#40;<\/span>size <span class=\"sy0\">+<\/span> <span class=\"nu0\">1<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; <span class=\"kw1\">private<\/span> <a href=\"http:\/\/www.google.com\/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+object\"><span class=\"kw3\">Object<\/span><\/a><span class=\"br0\">&#91;<\/span><span class=\"br0\">&#93;<\/span> grow<span class=\"br0\">&#40;<\/span><span class=\"kw4\">int<\/span> minCapacity<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">return<\/span> elementData <span class=\"sy0\">=<\/span> <a href=\"http:\/\/www.google.com\/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+arrays\"><span class=\"kw3\">Arrays<\/span><\/a>.<span class=\"me1\">copyOf<\/span><span class=\"br0\">&#40;<\/span>elementData,<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;newCapacity<span class=\"br0\">&#40;<\/span>minCapacity<span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">private<\/span> <span class=\"kw4\">int<\/span> newCapacity<span class=\"br0\">&#40;<\/span><span class=\"kw4\">int<\/span> minCapacity<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"co1\">\/\/ overflow-conscious code<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw4\">int<\/span> oldCapacity <span class=\"sy0\">=<\/span> elementData.<span class=\"me1\">length<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw4\">int<\/span> newCapacity <span class=\"sy0\">=<\/span> oldCapacity <span class=\"sy0\">+<\/span> <span class=\"br0\">&#40;<\/span>oldCapacity <span class=\"sy0\">&gt;&gt;<\/span> <span class=\"nu0\">1<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>newCapacity <span class=\"sy0\">-<\/span> minCapacity <span class=\"sy0\">&lt;=<\/span> <span class=\"nu0\">0<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>elementData <span class=\"sy0\">==<\/span> DEFAULTCAPACITY_EMPTY_ELEMENTDATA<span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">return<\/span> <a href=\"http:\/\/www.google.com\/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+math\"><span class=\"kw3\">Math<\/span><\/a>.<span class=\"me1\">max<\/span><span class=\"br0\">&#40;<\/span>DEFAULT_CAPACITY, minCapacity<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>minCapacity <span class=\"sy0\">&lt;<\/span> <span class=\"nu0\">0<\/span><span class=\"br0\">&#41;<\/span> <span class=\"co1\">\/\/ overflow<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">throw<\/span> <span class=\"kw1\">new<\/span> <a href=\"http:\/\/www.google.com\/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+outofmemoryerror\"><span class=\"kw3\">OutOfMemoryError<\/span><\/a><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">return<\/span> minCapacity<span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">return<\/span> <span class=\"br0\">&#40;<\/span>newCapacity <span class=\"sy0\">-<\/span> MAX_ARRAY_SIZE <span class=\"sy0\">&lt;=<\/span> <span class=\"nu0\">0<\/span><span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sy0\">?<\/span> newCapacity<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sy0\">:<\/span> hugeCapacity<span class=\"br0\">&#40;<\/span>minCapacity<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><\/div><\/td><\/tr><\/tbody><\/table><\/div>\n\n\n\n<p class=\"example_code\">Powi\u0119kszenie wewn\u0119trznej tablicy ArrayList, jak widzimy na powy\u017cszym listingu, zasadniczo sk\u0142ada si\u0119 z dw\u00f3ch etap\u00f3w. Pierwszym z nich jest obliczenie nowego rozmiaru tablicy. Odpowiada za to metoda <em>newCapacity. <\/em><\/p>\n\n\n\n<p>W jaki spos\u00f3b wyliczany jest rozmiar nowej tablicy? Clue logiki znajduje si\u0119 w linijce 251. Operator &gt;&gt;, jak dobrze wiemy, jest operatorem przesuni\u0119cia bitowego w prawo. Co si\u0119 stanie, jak wykonamy przesuni\u0119cie bitowe o 1 w prawo? Jest to odpowiednik mno\u017cenia przez liczb\u0119 2. Po\u0142owa tablicy jest ju\u017c zaj\u0119ta, wi\u0119c rozmiar tablicy zostanie zwi\u0119kszony o 50%. <\/p>\n\n\n\n<p class=\"example_code\">Zwr\u00f3\u0107 uwag\u0119 na wykorzystanie zmiennej <em>DEFAULT_CAPACITY<\/em> i <em>DEFAULTCAPACITY_EMPTY_ELEMENTDATA. <\/em>Je\u015bli u\u017cyli\u015bmy konstruktora bezargumentowego <em>ArrayList(), <\/em>dodanie pierwszego elementu spowoduje, \u017ce tablica zostanie rozszerzona do wielko\u015bci wskazanej przez zmienn\u0105 <em>DEFAULT_CAPACITY <\/em>(10 element\u00f3w). W przeciwnym wypadku u\u017cywane s\u0105 domy\u015blne regu\u0142y. <\/p>\n\n\n\n<p>W momencie, gdy posiadamy ju\u017c nowy rozmiar tablicy, kopiujemy zawarto\u015b\u0107 starej tablicy do nowej. W tym momencie mo\u017cemy ju\u017c doda\u0107 nowy element. <\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td>Nr powi\u0119kszenia<\/td><td>new ArrayList&lt;&gt;()<\/td><td>new ArrayList&lt;&gt;(0)<\/td><\/tr><tr><td>1<\/td><td>1 element<\/td><td>1 element<\/td><\/tr><tr><td>2<\/td><td>10 element<\/td><td>2 element<\/td><\/tr><tr><td>3<\/td><td>15 element<\/td><td>3 element<\/td><\/tr><tr><td>4<\/td><td>22 element<\/td><td>4 element<\/td><\/tr><tr><td>5<\/td><td>34 element<\/td><td>5 element<\/td><\/tr><tr><td>6<\/td><td>50 element<\/td><td>7 element<\/td><\/tr><tr><td>12<\/td><td>550 element<\/td><td>64 element<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"example_code\">Sp\u00f3jrz na powy\u017csz\u0105 tabel\u0119. Pokazuje ona moment wywo\u0142ania metody <em>grow <\/em>dla dw\u00f3ch metod stworzenia ArrayListy. Widzisz, dlaczego domy\u015blny rozmiar ArrayList zosta\u0142 ustawiony na 10? Przy dodawaniu 50 element\u00f3w tablica jest powi\u0119kszana tylko 6 razy. Je\u015bli wst\u0119pny rozmiar tablicy wynosi 0, podobny rozmiar uzyskamy dopiero po 12 wywo\u0142aniach metody <em>grow. <\/em><\/p>\n\n\n\n<p>Jaki mo\u017cemy wyci\u0105gn\u0105\u0107 wniosek? Je\u015bli wiemy, \u017ce:<\/p>\n\n\n\n<ul><li>b\u0119dziemy przechowywali bardzo du\u017c\u0105 ilo\u015b\u0107 element\u00f3w<\/li><li>kopiowanie przechowywanych element\u00f3w jest kosztowne<\/li><\/ul>\n\n\n\n<p>to powinni\u015bmy utworzy\u0107 ArrayList&lt;&gt; wst\u0119pnie deklaruj\u0105c ilo\u015b\u0107 element\u00f3w, jakie b\u0119dziemy przechowywali. Dzi\u0119ki temu unikniemy kosztownego kopiowania element\u00f3w przy ka\u017cdym powi\u0119kszeniu przestrzeni. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Usuwanie element\u00f3w z ArrayList<\/h2>\n\n\n\n<p>Jak dzia\u0142a usuwanie element\u00f3w z ArrayList? Skoro dodawanie zwi\u0119ksza rozmiar wewn\u0119trznej tablicy, to czy usuwanie b\u0119dzie j\u0105 zmniejsza\u0142o? Zobaczmy!<\/p>\n\n\n<div class=\"codecolorer-container java default\" style=\"overflow:auto;white-space:nowrap;width:100%;\"><table cellspacing=\"0\" cellpadding=\"0\"><tbody><tr><td class=\"line-numbers\"><div>669<br \/>670<br \/>671<br \/>672<br \/>673<br \/>674<br \/>675<br \/>676<br \/>677<br \/>678<br \/>679<br \/>680<br \/>681<br \/>682<br \/>683<br \/>684<br \/>685<br \/>686<br \/><\/div><\/td><td><div class=\"java codecolorer\">&nbsp; &nbsp; <span class=\"kw1\">public<\/span> E remove<span class=\"br0\">&#40;<\/span><span class=\"kw4\">int<\/span> index<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; Objects.<span class=\"me1\">checkIndex<\/span><span class=\"br0\">&#40;<\/span>index, size<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">final<\/span> <a href=\"http:\/\/www.google.com\/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+object\"><span class=\"kw3\">Object<\/span><\/a><span class=\"br0\">&#91;<\/span><span class=\"br0\">&#93;<\/span> es <span class=\"sy0\">=<\/span> elementData<span class=\"sy0\">;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; @SuppressWarnings<span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;unchecked&quot;<\/span><span class=\"br0\">&#41;<\/span> E oldValue <span class=\"sy0\">=<\/span> <span class=\"br0\">&#40;<\/span>E<span class=\"br0\">&#41;<\/span> es<span class=\"br0\">&#91;<\/span>index<span class=\"br0\">&#93;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; fastRemove<span class=\"br0\">&#40;<\/span>es, index<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">return<\/span> oldValue<span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<br \/>\n<br \/>\n<span class=\"kw1\">private<\/span> <span class=\"kw4\">void<\/span> fastRemove<span class=\"br0\">&#40;<\/span><a href=\"http:\/\/www.google.com\/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+object\"><span class=\"kw3\">Object<\/span><\/a><span class=\"br0\">&#91;<\/span><span class=\"br0\">&#93;<\/span> es, <span class=\"kw4\">int<\/span> i<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; modCount<span class=\"sy0\">++;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">final<\/span> <span class=\"kw4\">int<\/span> newSize<span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span><span class=\"br0\">&#40;<\/span>newSize <span class=\"sy0\">=<\/span> size <span class=\"sy0\">-<\/span> <span class=\"nu0\">1<\/span><span class=\"br0\">&#41;<\/span> <span class=\"sy0\">&gt;<\/span> i<span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <a href=\"http:\/\/www.google.com\/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+system\"><span class=\"kw3\">System<\/span><\/a>.<span class=\"me1\">arraycopy<\/span><span class=\"br0\">&#40;<\/span>es, i <span class=\"sy0\">+<\/span> <span class=\"nu0\">1<\/span>, es, i, newSize <span class=\"sy0\">-<\/span> i<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; es<span class=\"br0\">&#91;<\/span>size <span class=\"sy0\">=<\/span> newSize<span class=\"br0\">&#93;<\/span> <span class=\"sy0\">=<\/span> <span class=\"kw2\">null<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><\/div><\/td><\/tr><\/tbody><\/table><\/div>\n\n\n\n<p>W linijce 673 wykonywane jest &#8222;brzydkie&#8221; rzutowanie. Dzi\u0119ki temu mo\u017cemy zapisa\u0107 warto\u015b\u0107 usuwanego elementu aby potem m\u00f3c go zwr\u00f3ci\u0107. <\/p>\n\n\n\n<p class=\"example_code\">Najwa\u017cniejsza jest implementacja metody <em>fastRemove. <\/em>Sp\u00f3jrz na linijk\u0119 684. Je\u015bli usuwamy element ze &#8222;\u015brodka&#8221; tablicy, wszystkie elementy znajduj\u0105ce si\u0119 na lewo od niego przesuwamy o jedn\u0105 pozycj\u0119. Je\u015bli kasujemy element znajduj\u0105cy si\u0119 na ko\u0144cu listy &#8211; po prostu go nullujemy. Na ko\u0144cu zmniejszamy rozmiar tablicy (nie fizycznie &#8211; jedynie ten &#8222;widoczny dla u\u017cytkownika&#8221; czyli warto\u015b\u0107 zmiennej <em>size<\/em>). <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Serializacja\/deserializacja<\/h2>\n\n\n\n<p>Na koniec zajmijmy si\u0119 pewn\u0105 ciekawostk\u0105. Wr\u00f3\u0107my do fragmentu pierwszego listingu.<\/p>\n\n\n<div class=\"codecolorer-container java default\" style=\"overflow:auto;white-space:nowrap;width:100%;\"><div class=\"java codecolorer\"><span class=\"kw1\">transient<\/span> <a href=\"http:\/\/www.google.com\/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+object\"><span class=\"kw3\">Object<\/span><\/a><span class=\"br0\">&#91;<\/span><span class=\"br0\">&#93;<\/span> elementData<span class=\"sy0\">;<\/span><\/div><\/div>\n\n\n\n<p class=\"example_code\">Zwr\u00f3\u0107 uwag\u0119 na to, \u017ce <em>elementData<\/em> oznaczony jest s\u0142owem kluczowym <strong>transient. <\/strong>Oznacza to, \u017ce <em>elementData <\/em>nie zostanie poddany serializacji. Ale listy ArrayList mo\u017cna przecie\u017c serializowa\u0107! <strong>Jak to jest mo\u017cliwe? <\/strong>ArrayList korzysta z w\u0142asnego mechanizmu serializacji <a rel=\"noreferrer noopener\" href=\"https:\/\/stackoverflow.com\/questions\/9848129\/why-does-arraylist-use-transient-storage\" data-type=\"URL\" data-id=\"https:\/\/stackoverflow.com\/questions\/9848129\/why-does-arraylist-use-transient-storage\" target=\"_blank\">[3]<\/a>. Jej fragment zosta\u0142 przytoczony na poni\u017cszym listingu.<\/p>\n\n\n<div class=\"codecolorer-container java default\" style=\"overflow:auto;white-space:nowrap;width:100%;\"><table cellspacing=\"0\" cellpadding=\"0\"><tbody><tr><td class=\"line-numbers\"><div>886<br \/>887<br \/>888<br \/>889<br \/>890<br \/>891<br \/>892<br \/>893<br \/>894<br \/>895<br \/>896<br \/>897<br \/>898<br \/>899<br \/>900<br \/>901<br \/>902<br \/><\/div><\/td><td><div class=\"java codecolorer\">&nbsp; &nbsp; <span class=\"kw1\">private<\/span> <span class=\"kw4\">void<\/span> writeObject<span class=\"br0\">&#40;<\/span>java.<span class=\"me1\">io<\/span>.<a href=\"http:\/\/www.google.com\/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+objectoutputstream\"><span class=\"kw3\">ObjectOutputStream<\/span><\/a> s<span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">throws<\/span> java.<span class=\"me1\">io<\/span>.<a href=\"http:\/\/www.google.com\/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+ioexception\"><span class=\"kw3\">IOException<\/span><\/a> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"co1\">\/\/ Write out element count, and any hidden stuff<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw4\">int<\/span> expectedModCount <span class=\"sy0\">=<\/span> modCount<span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; s.<span class=\"me1\">defaultWriteObject<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"co1\">\/\/ Write out size as capacity for behavioral compatibility with clone()<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; s.<span class=\"me1\">writeInt<\/span><span class=\"br0\">&#40;<\/span>size<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"co1\">\/\/ Write out all elements in the proper order.<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">for<\/span> <span class=\"br0\">&#40;<\/span><span class=\"kw4\">int<\/span> i<span class=\"sy0\">=<\/span><span class=\"nu0\">0<\/span><span class=\"sy0\">;<\/span> i<span class=\"sy0\">&lt;<\/span>size<span class=\"sy0\">;<\/span> i<span class=\"sy0\">++<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; s.<span class=\"me1\">writeObject<\/span><span class=\"br0\">&#40;<\/span>elementData<span class=\"br0\">&#91;<\/span>i<span class=\"br0\">&#93;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>modCount <span class=\"sy0\">!=<\/span> expectedModCount<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">throw<\/span> <span class=\"kw1\">new<\/span> <a href=\"http:\/\/www.google.com\/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+concurrentmodificationexception\"><span class=\"kw3\">ConcurrentModificationException<\/span><\/a><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><\/div><\/td><\/tr><\/tbody><\/table><\/div>\n\n\n\n<p>Dlaczego zosta\u0142o wybrane takie rozwi\u0105zanie? Zwr\u00f3\u0107 uwag\u0119 na to, i\u017c wewn\u0119trzna tablica praktycznie zawsze b\u0119dzie mia\u0142a rozmiar wi\u0119kszy ni\u017c ilo\u015b\u0107 faktycznie zapisanych element\u00f3w. W przypadku korzystania z domy\u015blnego mechanizmu, puste pola tak\u017ce zosta\u0142yby zserializowane. Zaimplementowany przez tw\u00f3rc\u00f3w implementacji mechanizm zapobiega temu (linijki 896-898).<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Jak prawid\u0142owo korzysta\u0107 z ArrayList?<\/h2>\n\n\n\n<p>Skoro wiemy ju\u017c, jak dzia\u0142a ArrayList, spr\u00f3bujmy wyci\u0105gn\u0105\u0107 kilka wniosk\u00f3w. Najwa\u017cniejszym wnioskiem jest <strong>potrzeba dobrania odpowiedniego rozmiaru startowego w wypadku, gdy kopiowanie przechowywanych element\u00f3w jest kosztowne obliczeniowo. <\/strong>Pami\u0119tajmy te\u017c, \u017ce nie ka\u017cda operacja w ArrayList posiada tak\u0105 sam\u0105 wydajno\u015b\u0107. <\/p>\n\n\n\n<ul><li><strong>add(): <\/strong>Dodawanie pojedynczego elementu na ko\u0144cu listy jest najszybsze i zawsze wykonuje si\u0119 tyle samo czasu. Z\u0142o\u017cono\u015b\u0107 obliczeniowa: O(1). <\/li><li><strong>remove(): <\/strong>Posiada liniow\u0105 z\u0142o\u017cono\u015b\u0107 obliczeniow\u0105 O(n). Po pierwsze, trzeba znale\u017a\u0107 element, kt\u00f3ry chcemy usun\u0105\u0107. Po drugie natomiast &#8211; &#8222;wype\u0142ni\u0107 luk\u0119&#8221; przesuwaj\u0105c wszystkie elementy o 1 w lewo.<\/li><li><strong>add(index, element)<\/strong>: Dodanie elementu w \u015brodku tablicy b\u0119dzie mniej wi\u0119cej tak samo szybkie jak usuwanie element\u00f3w. Operacja ta posiada z\u0142o\u017cono\u015b\u0107 O(n). Dlaczego? Poniewa\u017c, podobnie jak przy usuwaniu, musimy przesun\u0105\u0107 wszystkie elementy listy aby zrobi\u0107 element na nowododawany. <\/li><li> <strong>get() &#8211; <\/strong>Zawsze trwa tyle samo czasu. Z\u0142o\u017cono\u015b\u0107 O(1). <\/li><li><strong>indexOf() &#8211; <\/strong>Czas trwania liniowo zale\u017cy od rozmiaru tablicy O(n). W najgorszym wypadku musimy przejrze\u0107 wszystkie elementy tablicy, aby znale\u017a\u0107 indeks szukanego. <\/li><li><strong>contains(): <\/strong>Implementacja wykorzystuje wewn\u0119trznie metod\u0119 <em>indexOf(). <\/em>Z\u0142o\u017cono\u015b\u0107 obliczeniowa b\u0119dzie wi\u0119c taka sama: O(n). <\/li><li><strong>size, isEmpty, iterator, listIterator &#8211; <\/strong>te operacje potrzebuja sta\u0142ego czasu O(1). <\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Co warto zapami\u0119ta\u0107?<\/h2>\n\n\n\n<p>Wynotujmy najwa\u017cniejsze rzeczy, kt\u00f3re warto mie\u0107 z ty\u0142u g\u0142owy (m.in. ze wzgl\u0119du na to, \u017ce pytania o takie szczeg\u00f3\u0142y czasami pojawiaj\u0105 si\u0119 na rozmowach kwalifikacyjnych):<\/p>\n\n\n\n<ul><li>ArrayList jest implementacj\u0105 tablicy o zmiennym rozmiarze. (to ka\u017cdy wie) <\/li><li>Implementacja ArrayList opiera si\u0119 na zwyk\u0142ej tablicy obiekt\u00f3w. <\/li><li>Jeden z konstruktor\u00f3w ArrayList pozwala na zdefiniowanie pocz\u0105tkowego rozmiaru. Wewn\u0119trzna tablica osi\u0105gnie taki rozmiar po dodaniu pierwszego elementu.<\/li><li>Domy\u015blnie tablica znajduj\u0105ca si\u0119 wewn\u0105trz ArrayList jest 10-elementowa. <\/li><li>Kiedy dodajemy nowy element, najpierw sprawdzamy czy si\u0119 on zmie\u015bci. Je\u015bli nie &#8211; musimy zwi\u0119kszy\u0107 tablic\u0119 o 50% jest aktualnej wielko\u015bci. <\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Zapisz si\u0119 do newslettera i polub m\u00f3j Fanpage<\/h2>\n\n\n\n<p>Podoba\u0142 ci si\u0119 ten artyku\u0142? Kliknij dzwoneczek (w lewej dolnej cz\u0119\u015bci ekranu) i zapisz si\u0119 na powiadomienia. Dzi\u0119ki temu, kiedy opublikuj\u0119 nowy artyku\u0142, dostaniesz o tym natychmiastow\u0105 informacj\u0119 i jednocze\u015bnie zainspirujesz mnie do dalszej pracy :). Polajkuj fanpage.<\/p>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-1 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<div style=\"padding:20px\" class=\"wp-block-tnp-minimal\"><p>Zapisz si\u0119 do newslettera!<\/p><div><div class=\"tnp tnp-subscription \">\n<form method=\"post\" action=\"https:\/\/www.kompikownia.pl\/?na=s\">\n<input type=\"hidden\" name=\"nlang\" value=\"\">\n<div class=\"tnp-field tnp-field-firstname\"><label for=\"tnp-1\">Imi\u0119 lub Imi\u0119 i Nazwisko<\/label>\n<input class=\"tnp-name\" type=\"text\" name=\"nn\" id=\"tnp-1\" value=\"\" placeholder=\"\"><\/div>\n<div class=\"tnp-field tnp-field-email\"><label for=\"tnp-2\">Email<\/label>\n<input class=\"tnp-email\" type=\"email\" name=\"ne\" id=\"tnp-2\" value=\"\" placeholder=\"\" required><\/div>\n<div class=\"tnp-field tnp-field-button\" style=\"text-align: left\"><input class=\"tnp-submit\" type=\"submit\" value=\"Subskrybuj\" style=\"background-color:undefined;\">\n<\/div>\n<\/form>\n<\/div>\n<\/div><\/div>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<div class=\"fb-page\" data-href=\"https:\/\/www.facebook.com\/kompikownia\/\" data-small-header=\"false\" data-adapt-container-width=\"true\" data-hide-cover=\"false\" data-show-facepile=\"true\"><blockquote cite=\"https:\/\/www.facebook.com\/kompikownia\/\" class=\"fb-xfbml-parse-ignore\"><a href=\"https:\/\/www.facebook.com\/kompikownia\/\">Kompikownia<\/a><\/blockquote><\/div>\n<\/div>\n<\/div>\n\n\n\n<p>Je\u015bli zauwa\u017cy\u0142e\u015b jaki\u015b b\u0142\u0105d, nie zrozumia\u0142e\u015b czego\u015b lub chcesz si\u0119 podzieli\u0107 niewspomnianymi w tym artykule wnioskami &#8211; \u015bmia\u0142o &#8211; napisz komentarz. B\u0119d\u0119 niezmiernie wdzi\u0119czny \ud83d\ude42 <\/p>\n\n\n\n<p>Dzi\u0119ki za lektur\u0119 i Powodzenia!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u0179r\u00f3d\u0142a<\/h2>\n\n\n\n[1] <a rel=\"noreferrer noopener\" href=\"https:\/\/docs.oracle.com\/javase\/7\/docs\/api\/java\/util\/RandomAccess.html\" target=\"_blank\">https:\/\/docs.oracle.com\/javase\/7\/docs\/api\/java\/util\/RandomAccess.html<\/a><br>[2] <a rel=\"noreferrer noopener\" href=\"https:\/\/www.geeksforgeeks.org\/internal-working-of-arraylist-in-java\/\" target=\"_blank\">https:\/\/www.geeksforgeeks.org\/internal-working-of-arraylist-in-java\/<\/a><br>[3] <a rel=\"noreferrer noopener\" href=\"https:\/\/stackoverflow.com\/questions\/9848129\/why-does-arraylist-use-transient-storage\" target=\"_blank\">https:\/\/stackoverflow.com\/questions\/9848129\/why-does-arraylist-use-transient-storage<\/a><br>[4] <a href=\"https:\/\/github.com\/AdoptOpenJDK\/openjdk-jdk11\/blob\/master\/src\/java.base\/share\/classes\/java\/util\/ArrayList.java\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/github.com\/AdoptOpenJDK\/openjdk-jdk11\/blob\/master\/src\/java.base\/share\/classes\/java\/util\/ArrayList.java<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p><span class=\"rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">Czas czytania:<\/span> <span class=\"rt-time\">3<\/span> <span class=\"rt-label rt-postfix\">minut<\/span><\/span> Programuj\u0105c w j\u0119zyku Java, z pewno\u015bci\u0105 wielokrotnie korzysta\u0142e\u015b z r\u00f3\u017cnego rodzaju list (ArrayList, LinkedList itd). Ale czy zastanawia\u0142e\u015b si\u0119 kiedy\u015b, jak wygl\u0105da ich wewn\u0119trzna implementacja? Analizowa\u0142e\u015b, jak wp\u0142ywa ona na &#8230;<\/p>\n","protected":false},"author":1,"featured_media":2636,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[77],"tags":[110,105,108,111,109,112,113],"_links":{"self":[{"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/posts\/2573"}],"collection":[{"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/comments?post=2573"}],"version-history":[{"count":63,"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/posts\/2573\/revisions"}],"predecessor-version":[{"id":2639,"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/posts\/2573\/revisions\/2639"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/media\/2636"}],"wp:attachment":[{"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/media?parent=2573"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/categories?post=2573"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/tags?post=2573"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}