{"id":142,"date":"2016-06-20T23:44:29","date_gmt":"2016-06-20T21:44:29","guid":{"rendered":"http:\/\/antek.atthost24.pl\/?p=142"},"modified":"2016-06-20T23:44:29","modified_gmt":"2016-06-20T21:44:29","slug":"kontrakt-hashcode-i-equals","status":"publish","type":"post","link":"https:\/\/blog.lantkowiak.pl\/index.php\/2016\/06\/20\/kontrakt-hashcode-i-equals\/","title":{"rendered":"Kontrakt hashCode i equals"},"content":{"rendered":"<p>Jedn\u0105 z pierwszych rzeczy, o kt\u00f3rych si\u0119 dowiadujemy ucz\u0105c si\u0119 Javy s\u0105 informacje na temat metod equals oraz\u00a0hashCode.\u00a0Informacje na temat kontraktu tych dw\u00f3ch metod s\u0105 bardzo istotne w programowaniu w Javie, szczeg\u00f3lnie w przypadku kolekcji, ale o tym b\u0119dzie kiedy indziej.<\/p>\n<h4>Kontrakt<\/h4>\n<p>Metody equals oraz hashCode powinny spe\u0142nia\u0107 poni\u017csze warunki:<\/p>\n<ul>\n<li>Je\u017celi x == y to x.equals(y) == true<\/li>\n<li>Je\u017celi x.equals(y) == true to x.hashCode() == y.hashCode()<\/li>\n<li>Je\u017celi\u00a0x.hashCode() == y.hashCode() to\u00a0x.equals(y) mo\u017ce zar\u00f3wno zwr\u00f3ci\u0107 true, jak i mo\u017ce zwr\u00f3ci\u0107 false<\/li>\n<\/ul>\n<p>Wszystkie warto\u015bci zwracane przez powy\u017csze funkcje musz\u0105 by\u0107 determistyczne &#8211; zawsze zwraca\u0107 te same warto\u015bci dla tych samym parametr\u00f3w.<\/p>\n<h4>Domy\u015blna implementacja<\/h4>\n<p>Metody hashCode i equals s\u0105 zdefiniowane w Object, czyli w klasie nadrz\u0119dnej dla wszystkich klas w Java. Domy\u015blne implementacje wygl\u0105daj\u0105 nast\u0119puj\u0105co:<\/p>\n<pre class=\"lang:java decode:true\" title=\"Metoda equals\">public boolean equals(Object obj) {\r\n\treturn (this == obj);\r\n}<\/pre>\n<p class=\"lang:java decode:true \" title=\"Metoda hashCode\">Domy\u015blna implementacja metody equals opiera si\u0119 na sprawdzeniu czy przekazany obiekt jest t\u0105 sam\u0105 instancj\u0105, co obiekt, na kt\u00f3rym wywo\u0142ano metod\u0119 equals. Jak wida\u0107 domy\u015blna implementacja w \u017caden spos\u00f3b nie opiera si\u0119 na atrybutach klasy.<\/p>\n<pre class=\"lang:java decode:true\" title=\"Metoda hashCode\">public native int hashCode();<\/pre>\n<p>Klasa Object nie ma natomiast zdefiniowanego cia\u0142a\u00a0metody hashCode. Ka\u017cda implementacja JVM dostarcza swoj\u0105 wersje tej metody. Zazwyczaj jest to adres pami\u0119ci, pod kt\u00f3rym znajduje si\u0119 obiekt, zamieniony na typ integer. Podej\u015bcie takie by\u0142oby prawid\u0142owe, gdyby ka\u017cdy obiekt by\u0142 unikalny. W przypadku kiedy dwa obiekty s\u0105 identyczne (bazuj\u0105c na atrybutach klasy) implementacja taka nie spe\u0142nia kontraktu tej metody.<\/p>\n<h4>Przyk\u0142adowe implementacje<\/h4>\n<p>Oczywi\u015bcie powy\u017csze metody mo\u017cemy (a cz\u0119sto wr\u0119cz musimy) nadpisa\u0107 i dostosowa\u0107 do naszych potrzeb. Za\u0142\u00f3\u017cmy, \u017ce mamy poni\u017csz\u0105 klas\u0119, do kt\u00f3rej chcemy dopisa\u0107 nasze dwie metody, o kt\u00f3rych rozmawiamy.<\/p>\n<pre class=\"lang:java decode:true \" title=\"klasa Person\">class Person {\r\n\tprivate final String name;\r\n\tprivate final int age;\r\n\r\n\tpublic Person(final String name, final int age) {\r\n\t\tthis.name = name;\r\n\t\tthis.age = age;\r\n\t}\r\n\r\n\tpublic String getName() {\r\n\t\treturn name;\r\n\t}\r\n\r\n\tpublic int getAge() {\r\n\t\treturn age;\r\n\t}\r\n}<\/pre>\n<p>Przyk\u0142adowe implementacja metody hashCode mog\u0105 wygl\u0105da\u0107 nast\u0119puj\u0105co:<\/p>\n<pre class=\"lang:java decode:true\" title=\"Przyk\u0142adowa implementacja hashCode\">@Override\r\npublic int hashCode() {\r\n\tfinal int prime = 31;\r\n\tint result = 1;\r\n\tresult = prime * result + age;\r\n\tresult = prime * result + ((name == null) ? 0 : name.hashCode());\r\n\r\n\treturn result;\r\n}<\/pre>\n<p>Jak wida\u0107 warto\u015b\u0107 hashCode jest wyliczana przy u\u017cyciu mno\u017cenia i dodawanie na podstawie wszystkich p\u00f3l klasy.<\/p>\n<p>Implementacja equals dla naszej klasy mo\u017ce wygl\u0105da\u0107 tak:<\/p>\n<pre class=\"lang:default decode:true\" title=\"Przyk\u0142adowa implementacja equals\">@Override\r\npublic boolean equals(Object obj) {\r\n\tif (this == obj) {\r\n\t\treturn true;\r\n\t}\r\n\tif (obj == null) {\r\n\t\treturn false;\r\n\t}\r\n\tif (getClass() != obj.getClass()) {\r\n\t\treturn false;\r\n\t}\r\n\tfinal Person that = (Person) obj;\r\n\tif (age != that.age) {\r\n\t\treturn false;\r\n\t}\r\n\tif (name == null) {\r\n\t\tif (that.name != null) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\t} else if (!name.equals(that.name)) {\r\n\t\treturn false;\r\n\t}\r\n\treturn true;\r\n}<\/pre>\n<p>Tutaj ju\u017c si\u0119 dziej\u0119 troch\u0119 wi\u0119cej&#8230;\u00a0albo przynajmniej wygl\u0105da jakby si\u0119 dzia\u0142o wi\u0119cej.<br \/>\nW liniach 3-11 sprawdzamy identyczno\u015b\u0107 obiekt\u00f3w na poziomie samego obiektu, a nie jego atrybut\u00f3w. Sprawdzamy czy:<\/p>\n<ul>\n<li>przekazany obiekt jest tym samym obiektem, na kt\u00f3rym zosta\u0142a wywo\u0142ana metoda &#8211; je\u017celi jest\u00a0to oczywi\u015bcie zwracamy true<\/li>\n<li>przekazany obiekt nie jest nullem &#8211; je\u017celi jest to zwracamy false &#8211; obiekt, na ktorym wywo\u0142ali\u015bmy metod\u0119 z oczywistych powod\u00f3w nie mo\u017ce by\u0107 nullem \ud83d\ude42<\/li>\n<li>oba obiekty s\u0105 tego samego typu &#8211; je\u017celi nie s\u0105 to oczywi\u015bcie zwracamy false<\/li>\n<\/ul>\n<p>Je\u017celi obiekt przejdzie te 3 warunki to jest rzutowany na nasz typ klasy, a nast\u0119pnie ka\u017cde pole klasy jest por\u00f3wnywane. Je\u017celi, kt\u00f3re\u015b z por\u00f3wnywanych p\u00f3l jest inne to oczywi\u015bcie zwracamy false, a w przeciwnym przypadku przechodzimy dalej. Kiedy ju\u017c wszystkie pola zosta\u0142y sprawdzony to zwracamy true.<\/p>\n<h4>Bardziej praktyczna\u00a0implementacja<\/h4>\n<p>Implementacje powy\u017cszych metod nie s\u0105 trudne, ale zajmuj\u0105 troch\u0119 linii kodu (szczeg\u00f3lnie equals). Dodatkowo implementuj\u0105c r\u0119cznie te metody dla klas z wi\u0119ksz\u0105 ilo\u015bci\u0105 p\u00f3\u0142 \u0142atwo o pomy\u0142ke. Co prawda ka\u017cde IDE potrafi wygenerowa\u0107 implementacje powy\u017cszych metod na podstawie p\u00f3l klasy, ale wci\u0105\u017c zostaje problem pierwszy &#8211; du\u017co linii i brzydko to wygl\u0105da \ud83d\ude09<\/p>\n<p>Bardzo polecam u\u017cywanie bibliotek, kt\u00f3re zawieraj\u0105 wbudowany builder&#8217;y do tych metod. Jedn\u0105 z takich bibliotek jest common-lang od Apache.<br \/>\nImplementacja hashCode przy u\u017cyciu tej metody wygl\u0105da nast\u0119puj\u0105co:<\/p>\n<pre class=\"lang:java decode:true\" title=\"Implementacja hashCode przy u\u017cycou biblioteki common-lang\">@Override\r\npublic int hashCode() {\r\n\treturn new HashCodeBuilder().append(age).append(name).toHashCode();\r\n}<\/pre>\n<p>Jak wida\u0107 kod dla tej metody zosta\u0142 zdecydowanie uproszczony i jest bardziej przejrzysty.<\/p>\n<p>Implementacja metody equals mo\u017ce wygl\u0105da\u0107 na przyk\u0142ad tak:<\/p>\n<pre class=\"lang:java decode:true\" title=\"Implementacja equals przy u\u017cyciu common-lang\">@Override\r\npublic boolean equals(Object obj) {\r\n\tif (this == obj) {\r\n\t\treturn true;\r\n\t}\r\n\tif (obj == null) {\r\n\t\treturn false;\r\n\t}\r\n\tif (getClass() != obj.getClass()) {\r\n\t\treturn false;\r\n\t}\r\n\tfinal Person that = (Person) obj;\r\n\treturn new EqualsBuilder().append(this.age, that.age).append(this.name, that.name).isEquals();\r\n}<\/pre>\n<p>Jak wida\u0107 kod w tym przypadku r\u00f3wnie\u017c si\u0119 troch\u0119 upro\u015bci\u0142. Trzy pierwsze if&#8217;y co prawda zosta\u0142y, ale reszta kodu zosta\u0142a zdecydowanie skr\u00f3cona i jest bardziej czytelna.<\/p>\n<p>Jak wida\u0107 dzi\u0119ki u\u017cyciu kodu z biblioteki mogli\u015bmy stworzy\u0107 nasze metody pisz\u0105c mniej kodu, kt\u00f3ry jest jednak bardziej czytelny i przejrzysty.<\/p>\n<h4>A mo\u017ce by tak jeszcze co\u015b ulepszy\u0107?<\/h4>\n<p>Patrz\u0105c na implementacje metody equals mo\u017cna by si\u0119 zastanowi\u0107 czy u\u017cycie instanceof zamiast drugiego i trzeciego if&#8217;a nie by\u0142oby dobrym pomys\u0142em. Wtedy nasza klasa mog\u0142aby wygl\u0105da\u0107 w nast\u0119puj\u0105cy spos\u00f3b:<\/p>\n<pre class=\"lang:default decode:true \" title=\"Metoda equals z u\u017cyciem instanceof\">class Person {\r\n\tprivate final String name;\r\n\tprivate final int age;\r\n\r\n\tpublic Person(final String name, final int age) {\r\n\t\tthis.name = name;\r\n\t\tthis.age = age;\r\n\t}\r\n\r\n\tpublic String getName() {\r\n\t\treturn name;\r\n\t}\r\n\r\n\tpublic int getAge() {\r\n\t\treturn age;\r\n\t}\r\n\r\n\t@Override\r\n\tpublic int hashCode() {\r\n\t\treturn new HashCodeBuilder().append(age).append(name).toHashCode();\r\n\t}\r\n\r\n\t@Override\r\n\tpublic boolean equals(Object obj) {\r\n\t\tif (this == obj) {\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tif (!(obj instanceof Person)) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\tfinal Person that = (Person) obj;\r\n\t\treturn new EqualsBuilder().append(this.age, that.age).append(this.name, that.name).isEquals();\r\n\t}\r\n}<\/pre>\n<p>Dzi\u0119ki takiemu podej\u015bciu 'oszcz\u0119dzamy&#8217; jednego if&#8217;a, a wszystko dzia\u0142a jak dzia\u0142a\u0142o. Chocia\u017c&#8230;<\/p>\n<p>Sp\u00f3jrzmy na poni\u017csz\u0105 klase:<\/p>\n<pre class=\"lang:java decode:true\" title=\"klasa Student\">class Student extends Person {\r\n\tprivate final String school;\r\n\r\n\tpublic Student(final String name, final int age, final String school) {\r\n\t\tsuper(name, age);\r\n\t\tthis.school= school;\r\n\t}\r\n\r\n\tpublic String getSchool() {\r\n\t\treturn school;\r\n\t}\r\n\r\n\t@Override\r\n\tpublic int hashCode() {\r\n\t\treturn new HashCodeBuilder().appendSuper(super.hashCode())\r\n\t\t\t\t.append(school).toHashCode();\r\n\t}\r\n\r\n\t@Override\r\n\tpublic boolean equals(Object obj) {\r\n\t\tif (this == obj) {\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tif (!(obj instanceof Student)) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\tfinal Student that = (Student) obj;\r\n\t\treturn new EqualsBuilder().appendSuper(super.equals(that))\r\n\t\t\t\t.append(this.school, that.school).isEquals();\r\n\t}\r\n}<\/pre>\n<p>Stworzyli\u015bmy klas\u0119 Student, kt\u00f3ra dziedziczy po Person. Nasza nowa klasa zawiera dodatkowe pole 'school&#8217;.<\/p>\n<p>Zr\u00f3bmy teraz co\u015b takiego:<\/p>\n<pre class=\"lang:java decode:true\">final Person p = new Person(\"Adam\", 15);\r\nfinal Student s = new Student(\"Adam\", 15, \"uj\");\r\n\t\t\r\nSystem.out.println(p.equals(s)); \/\/ true\r\nSystem.out.println(s.equals(p)); \/\/ false<\/pre>\n<p>Jak wida\u0107 dochodzimy do sytuacji, gdzie tworzymy dwa r\u00f3\u017cne obiekty i w zale\u017cno\u015bci od tego, kt\u00f3ry do kt\u00f3rego por\u00f3wnamy to otrzymujemy r\u00f3\u017cne wyniki.\u00a0R\u00f3wno\u015b\u0107 powinna by\u0107 relacj\u0105 symetryczn\u0105, a taka sytuacja zdecydowanie j\u0105 narusza.<\/p>\n<p>Czy to oznacza, \u017ce to podej\u015bcie jest b\u0142\u0119dne? Odpowied\u017a jest bardzo prosta i brzmi: to zale\u017cy \ud83d\ude42<\/p>\n<p>Wersja equals z getClass jest, powiedzmy, 'restrykcyjna&#8217;, ale za to prosta i intuicyjna. Por\u00f3wnywany obiekt musi by\u0107 dok\u0142adnie tego samego typu co obiekt, do kt\u00f3rego jest por\u00f3wnywany.<\/p>\n<p>Druga wersje mo\u017ce narobi\u0107\u00a0nam troch\u0119\u00a0ambarasu, lecz zostawia troch\u0119 wi\u0119cej swobody. Istotnym przypadkiem, kiedy takie podej\u015bcie mo\u017ce by\u0107 konieczne jest por\u00f3wnywanie obiekt\u00f3w, kt\u00f3re s\u0105 zarz\u0105dzane przez jaki\u015b framework\u00a0np. cz\u0119\u015b\u0107 implementacji JPA opakowuje encje. W takiej sytuacji, dzi\u0119ki u\u017cyciu instanceof w metodzie equals jeste\u015bmy w stanie w poprawny spos\u00f3b por\u00f3wnywa\u0107 takie obiekty.<\/p>\n<p>Jak wida\u0107 obydwa sposoby implementacji metody equals maj\u0105 swoje zastosowania. Najwa\u017cniejsze, \u017ceby \u015bwiadomie wybiera\u0107 podej\u015bcie, kt\u00f3rego potrzebujemy \ud83d\ude42<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Jedn\u0105 z pierwszych rzeczy, o kt\u00f3rych si\u0119 dowiadujemy ucz\u0105c si\u0119 Javy s\u0105 informacje na temat metod equals oraz\u00a0hashCode.\u00a0Informacje na temat kontraktu tych dw\u00f3ch metod s\u0105 bardzo istotne w&#8230;<\/p>\n","protected":false},"author":1,"featured_media":149,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[9,10,8],"class_list":["post-142","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-java","tag-equals","tag-hashcode","tag-java"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v21.4 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Kontrakt hashCode i equals - Lukasz Antkowiak&#039;s blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/blog.lantkowiak.pl\/index.php\/2016\/06\/20\/kontrakt-hashcode-i-equals\/\" \/>\n<meta property=\"og:locale\" content=\"pl_PL\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Kontrakt hashCode i equals - Lukasz Antkowiak&#039;s blog\" \/>\n<meta property=\"og:description\" content=\"Jedn\u0105 z pierwszych rzeczy, o kt\u00f3rych si\u0119 dowiadujemy ucz\u0105c si\u0119 Javy s\u0105 informacje na temat metod equals oraz\u00a0hashCode.\u00a0Informacje na temat kontraktu tych dw\u00f3ch metod s\u0105 bardzo istotne w...\" \/>\n<meta property=\"og:url\" content=\"https:\/\/blog.lantkowiak.pl\/index.php\/2016\/06\/20\/kontrakt-hashcode-i-equals\/\" \/>\n<meta property=\"og:site_name\" content=\"Lukasz Antkowiak&#039;s blog\" \/>\n<meta property=\"article:published_time\" content=\"2016-06-20T21:44:29+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/blog.lantkowiak.pl\/wp-content\/uploads\/2016\/06\/hashtables-3.png\" \/>\n\t<meta property=\"og:image:width\" content=\"800\" \/>\n\t<meta property=\"og:image:height\" content=\"379\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"\u0141ukasz Antkowiak\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Napisane przez\" \/>\n\t<meta name=\"twitter:data1\" content=\"\u0141ukasz Antkowiak\" \/>\n\t<meta name=\"twitter:label2\" content=\"Szacowany czas czytania\" \/>\n\t<meta name=\"twitter:data2\" content=\"7 minut\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/blog.lantkowiak.pl\/index.php\/2016\/06\/20\/kontrakt-hashcode-i-equals\/\",\"url\":\"https:\/\/blog.lantkowiak.pl\/index.php\/2016\/06\/20\/kontrakt-hashcode-i-equals\/\",\"name\":\"Kontrakt hashCode i equals - Lukasz Antkowiak&#039;s blog\",\"isPartOf\":{\"@id\":\"https:\/\/blog.lantkowiak.pl\/#website\"},\"datePublished\":\"2016-06-20T21:44:29+00:00\",\"dateModified\":\"2016-06-20T21:44:29+00:00\",\"author\":{\"@id\":\"https:\/\/blog.lantkowiak.pl\/#\/schema\/person\/009bfc4db220c225786c59b1748ba1e6\"},\"breadcrumb\":{\"@id\":\"https:\/\/blog.lantkowiak.pl\/index.php\/2016\/06\/20\/kontrakt-hashcode-i-equals\/#breadcrumb\"},\"inLanguage\":\"pl-PL\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/blog.lantkowiak.pl\/index.php\/2016\/06\/20\/kontrakt-hashcode-i-equals\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/blog.lantkowiak.pl\/index.php\/2016\/06\/20\/kontrakt-hashcode-i-equals\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Strona g\u0142\u00f3wna\",\"item\":\"https:\/\/blog.lantkowiak.pl\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Kontrakt hashCode i equals\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/blog.lantkowiak.pl\/#website\",\"url\":\"https:\/\/blog.lantkowiak.pl\/\",\"name\":\"Lukasz Antkowiak&#039;s blog\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/blog.lantkowiak.pl\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"pl-PL\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/blog.lantkowiak.pl\/#\/schema\/person\/009bfc4db220c225786c59b1748ba1e6\",\"name\":\"\u0141ukasz Antkowiak\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"pl-PL\",\"@id\":\"https:\/\/blog.lantkowiak.pl\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/e18e2bfe319da9b5757cf7f7ae1bfecf?s=96&d=monsterid&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/e18e2bfe319da9b5757cf7f7ae1bfecf?s=96&d=monsterid&r=g\",\"caption\":\"\u0141ukasz Antkowiak\"},\"description\":\"dd\",\"url\":\"https:\/\/blog.lantkowiak.pl\/index.php\/author\/antek\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Kontrakt hashCode i equals - Lukasz Antkowiak&#039;s blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/blog.lantkowiak.pl\/index.php\/2016\/06\/20\/kontrakt-hashcode-i-equals\/","og_locale":"pl_PL","og_type":"article","og_title":"Kontrakt hashCode i equals - Lukasz Antkowiak&#039;s blog","og_description":"Jedn\u0105 z pierwszych rzeczy, o kt\u00f3rych si\u0119 dowiadujemy ucz\u0105c si\u0119 Javy s\u0105 informacje na temat metod equals oraz\u00a0hashCode.\u00a0Informacje na temat kontraktu tych dw\u00f3ch metod s\u0105 bardzo istotne w...","og_url":"https:\/\/blog.lantkowiak.pl\/index.php\/2016\/06\/20\/kontrakt-hashcode-i-equals\/","og_site_name":"Lukasz Antkowiak&#039;s blog","article_published_time":"2016-06-20T21:44:29+00:00","og_image":[{"width":800,"height":379,"url":"https:\/\/blog.lantkowiak.pl\/wp-content\/uploads\/2016\/06\/hashtables-3.png","type":"image\/png"}],"author":"\u0141ukasz Antkowiak","twitter_card":"summary_large_image","twitter_misc":{"Napisane przez":"\u0141ukasz Antkowiak","Szacowany czas czytania":"7 minut"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/blog.lantkowiak.pl\/index.php\/2016\/06\/20\/kontrakt-hashcode-i-equals\/","url":"https:\/\/blog.lantkowiak.pl\/index.php\/2016\/06\/20\/kontrakt-hashcode-i-equals\/","name":"Kontrakt hashCode i equals - Lukasz Antkowiak&#039;s blog","isPartOf":{"@id":"https:\/\/blog.lantkowiak.pl\/#website"},"datePublished":"2016-06-20T21:44:29+00:00","dateModified":"2016-06-20T21:44:29+00:00","author":{"@id":"https:\/\/blog.lantkowiak.pl\/#\/schema\/person\/009bfc4db220c225786c59b1748ba1e6"},"breadcrumb":{"@id":"https:\/\/blog.lantkowiak.pl\/index.php\/2016\/06\/20\/kontrakt-hashcode-i-equals\/#breadcrumb"},"inLanguage":"pl-PL","potentialAction":[{"@type":"ReadAction","target":["https:\/\/blog.lantkowiak.pl\/index.php\/2016\/06\/20\/kontrakt-hashcode-i-equals\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/blog.lantkowiak.pl\/index.php\/2016\/06\/20\/kontrakt-hashcode-i-equals\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Strona g\u0142\u00f3wna","item":"https:\/\/blog.lantkowiak.pl\/"},{"@type":"ListItem","position":2,"name":"Kontrakt hashCode i equals"}]},{"@type":"WebSite","@id":"https:\/\/blog.lantkowiak.pl\/#website","url":"https:\/\/blog.lantkowiak.pl\/","name":"Lukasz Antkowiak&#039;s blog","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/blog.lantkowiak.pl\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"pl-PL"},{"@type":"Person","@id":"https:\/\/blog.lantkowiak.pl\/#\/schema\/person\/009bfc4db220c225786c59b1748ba1e6","name":"\u0141ukasz Antkowiak","image":{"@type":"ImageObject","inLanguage":"pl-PL","@id":"https:\/\/blog.lantkowiak.pl\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/e18e2bfe319da9b5757cf7f7ae1bfecf?s=96&d=monsterid&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/e18e2bfe319da9b5757cf7f7ae1bfecf?s=96&d=monsterid&r=g","caption":"\u0141ukasz Antkowiak"},"description":"dd","url":"https:\/\/blog.lantkowiak.pl\/index.php\/author\/antek\/"}]}},"_links":{"self":[{"href":"https:\/\/blog.lantkowiak.pl\/index.php\/wp-json\/wp\/v2\/posts\/142","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.lantkowiak.pl\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.lantkowiak.pl\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.lantkowiak.pl\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.lantkowiak.pl\/index.php\/wp-json\/wp\/v2\/comments?post=142"}],"version-history":[{"count":27,"href":"https:\/\/blog.lantkowiak.pl\/index.php\/wp-json\/wp\/v2\/posts\/142\/revisions"}],"predecessor-version":[{"id":173,"href":"https:\/\/blog.lantkowiak.pl\/index.php\/wp-json\/wp\/v2\/posts\/142\/revisions\/173"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.lantkowiak.pl\/index.php\/wp-json\/wp\/v2\/media\/149"}],"wp:attachment":[{"href":"https:\/\/blog.lantkowiak.pl\/index.php\/wp-json\/wp\/v2\/media?parent=142"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.lantkowiak.pl\/index.php\/wp-json\/wp\/v2\/categories?post=142"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.lantkowiak.pl\/index.php\/wp-json\/wp\/v2\/tags?post=142"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}