Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Исследование роли accessOrder в жизни, LinkedHashMap (для не слабых людей) 
:(
    Опции темы
Royan
Дата 22.4.2008, 11:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Dreamer
***


Профиль
Группа: Участник Клуба
Сообщений: 1708
Регистрация: 14.9.2002
Где: Лондон

Репутация: 3
Всего: 15



Есть у данной исплементации Map конструктор со следующей сигнатурой: LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) 

Я решил поэкспериментировать, вот мои результаты:

Код

import java.util.LinkedHashMap;

public class LinkedHashMapTest {
    public static void main(String[] args) {
        final int LEN = 10;
        LinkedHashMap<Integer, String> map = new LinkedHashMap<Integer, String>(
                LEN, 0.75f, true);
        for (int i = 0; i < LEN; i++) {
            map.put(i, new String(">" + i));
        }
        
        for (Integer i : map.keySet()) {
            System.err.println("=" + map.get(i));
            System.err.println("=" + map.get(i+1));
            System.err.println("=" + map.get(i+2));
            System.err.println("=" + map.get(i+3));
            System.err.println("=" + map.get(i+4));
            System.err.println("=" + map.get(i+5));
            System.err.println("=" + map.get(i+6));
            System.err.println("=" + map.get(i+7));
            System.err.println("=" + map.get(i+8));
            break;
        }
        
        for (Integer i : map.keySet()) {
            System.err.println("!" + map.get(i));
            break;
        }        
    }
}


Output:
Цитата

=>0
=>1
=>2
=>3
=>4
=>5
=>6
=>7
=>8
!>9


Если к-то не заметил, то в случае когда параметр accessOrder выставлен в true, то всякий раз когда мы пользуемся итератором, последний элемент к которому произошло обращение при помощи LinkedHashMap#get(), LinkedHashMap#put() и LinkedHashMap#putAll() переходит в конец списка (в случае putAll() для каждого добавленного элемента).

Объяснил коряво ну суть такая. Если accessOrder в true, и мы внутри цикла итерируем по LinkedHashMap, то всякий раз когда мы делаем вызов вышеописанных методов внутри нашего цикла, то следующий раз когда мы будем итерировать то начнем с того элемента который дернули последним.

Именно поэтому в строке 26 авыводится 9, а не 0 (как было бы если бы accessOrder был выставлен в false) break'и в циклах стоят, дабы не спровоцировать ConcurrentModificationException, поскольку опять же обращение get(), put() и putAll() модифицирует внутреннюю структуру списка.

Еще одно дополнение, вызовы get() должны быть последовательным поэтому если сразу дернуть, к примеру, 2-й элемент, то все будет работать в обычных условиях:

Код

import java.util.LinkedHashMap;

public class LinkedHashMapTest {
    public static void main(String[] args) {
        final int LEN = 10;
        LinkedHashMap<Integer, String> map = new LinkedHashMap<Integer, String>(
                LEN, 0.75f, true);
        for (int i = 0; i < LEN; i++) {
            map.put(i, new String(">" + i));
        }
        
        for (Integer i : map.keySet()) {
            System.err.println("=" + map.get(i+2));
            break;
        }
        
        for (Integer i : map.keySet()) {
            System.err.println("!" + map.get(i));
            System.err.println("!" + map.get(i+1));
            System.err.println("!" + map.get(i+2));
            System.err.println("!" + map.get(i+3));
            System.err.println("!" + map.get(i+4));
            break;
        }
    }
}



Output:
Цитата

=>2
!>0
!>1
!>2
!>3
!>4


Все это я затеял с тем, чтобы понять зачем вообще весь этот огород было городить? В каких задачах нужна подобная функциональность?



--------------------
Открыта вакансия Junior Java Developer'а в нашем лондонском офисе, подробнее можно узнать здесь
PM MAIL MSN   Вверх
Andy_L20066
  Дата 22.4.2008, 12:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 177
Регистрация: 10.3.2008

Репутация: нет
Всего: 1



интересный вопрос.... ну могу сказать следующее:
если accessOrder у нас true и выполняется (Integer i : map.keySet()) тогда переменная 'i' будет постоянно отвечать за индекс первого елемента в мапе... то есть это может быть 9, как в первом случае... потому что этот елемент сейчас на первом месте в мапе... тоесть вернется елемент с ключем 9...
или если во втором случае у нас был доступ сначала ко второму елементу(map.get(i+2)), потом map.get(i) вернуло 0... ну правильно... потому что второй елемент поместился в конец мапы.... а на первом месте сейчас елемент с ключем 0....если accessOrder у нас false - тогда (Integer i : map.keySet()) будет нулевой... и будет возвращатся елемент с ключем '0'...
тоесть с тем какие елементы  в даный момент возвращаются, на мой взгляд - все логично...

думаю функциональность такая нужна для того чтобы можно было иметь копию мапы из точным порядком елементов...  хотя черт его знает....  smile 

поправьте если может чьо не так изложил...


PM MAIL ICQ   Вверх
LSD
Дата 22.4.2008, 16:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15718
Регистрация: 24.3.2004
Где: Dublin

Репутация: 210
Всего: 538



Цитата(Royan @  22.4.2008,  12:18 Найти цитируемый пост)
Все это я затеял с тем, чтобы понять зачем вообще весь этот огород было городить? В каких задачах нужна подобная функциональность?

Там же в доке достаточно ясно написано - для организации LRU кешей, списков и т.п.


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
Royan
  Дата 24.4.2008, 12:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Dreamer
***


Профиль
Группа: Участник Клуба
Сообщений: 1708
Регистрация: 14.9.2002
Где: Лондон

Репутация: 3
Всего: 15



Цитата(LSD @  22.4.2008,  13:32 Найти цитируемый пост)
LRU кешей, списков и т.п.

Окей возьмем к примеру LRU кэш. Например мне нужно вытащить из LinkedHashMap'а 5-ый элемент... это что же получается - для того, чтобы добраться до него я должен буду проитерировать по элементам с 1 по 4-ый, чтобы потом взять сверху 5-ый? Тогда теряется суть кэша. В какой-то одной стороне должны оказываться самые часто используемые элементы, в другой самые редко используемые, а тут я взял и перебрал все с 1 по 4 как будто они мне были нужны.


--------------------
Открыта вакансия Junior Java Developer'а в нашем лондонском офисе, подробнее можно узнать здесь
PM MAIL MSN   Вверх
LSD
Дата 24.4.2008, 12:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15718
Регистрация: 24.3.2004
Где: Dublin

Репутация: 210
Всего: 538



Цитата(Royan @  24.4.2008,  13:13 Найти цитируемый пост)
Например мне нужно вытащить из LinkedHashMap'а 5-ый элемент... это что же получается - для того, чтобы добраться до него я должен буду проитерировать по элементам с 1 по 4-ый, чтобы потом взять сверху 5-ый? Тогда теряется суть кэша. В какой-то одной стороне должны оказываться самые часто используемые элементы, в другой самые редко используемые, а тут я взял и перебрал все с 1 по 4 как будто они мне были нужны.

Из Map никто не вытаскивает элементы по номеру, т.к. в общем случае (например при использовании HashMap) неизвестно что там будет под пятым номером. Элементы из Map вытаскиваются по ключу. 
Итератор по Map используется или для полного перебора всех элементов, или для перебора их в определенном порядке (SortedMap или LRU Map) который индивидуален для каждого типа Map.


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
Royan
Дата 27.4.2008, 20:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Dreamer
***


Профиль
Группа: Участник Клуба
Сообщений: 1708
Регистрация: 14.9.2002
Где: Лондон

Репутация: 3
Всего: 15



Цитата(LSD @  24.4.2008,  09:54 Найти цитируемый пост)
Итератор по Map используется или для полного перебора всех элементов, или для перебора их в определенном порядке (SortedMap или LRU Map) который индивидуален для каждого типа Map.

Проблема в том, что в LRU реализации LinkedHashMap невозможно проитерировать более одного элемента за раз, так как внутренняя структура карты меняется после каждого выхова метода get


--------------------
Открыта вакансия Junior Java Developer'а в нашем лондонском офисе, подробнее можно узнать здесь
PM MAIL MSN   Вверх
LSD
Дата 27.4.2008, 22:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15718
Регистрация: 24.3.2004
Где: Dublin

Репутация: 210
Всего: 538



Цитата(Royan @  27.4.2008,  21:15 Найти цитируемый пост)
Проблема в том, что в LRU реализации LinkedHashMap невозможно проитерировать более одного элемента за раз, так как внутренняя структура карты меняется после каждого выхова метода get

Возможно, просто надо использовать правильный итератор smile 
Код

final int LEN = 10;
LinkedHashMap<Integer, String> map = new LinkedHashMap<Integer, String>(LEN, 0.75f, true);
for(int i = 0; i < LEN; i++)
{
  map.put(i, "(" + i + ")");
}

for(Map.Entry<Integer, String> entry : map.entrySet())
  System.out.println(entry.getKey() + " => " + entry.getValue());



--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
Royan
Дата 28.4.2008, 00:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Dreamer
***


Профиль
Группа: Участник Клуба
Сообщений: 1708
Регистрация: 14.9.2002
Где: Лондон

Репутация: 3
Всего: 15



Цитата(LSD @  27.4.2008,  19:57 Найти цитируемый пост)
Возможно, просто надо использовать правильный итератор

Итератор заработал - эффект пропал, это я, конечно, не к тому, чтобы ты полез дебажить smile просто забавная фукнциональность

Код

import java.util.LinkedHashMap;
import java.util.Map;

public class LinkedHashMapTest {
    public static void main(String[] args) {
        final int LEN = 10;
        LinkedHashMap<Integer, String> map = new LinkedHashMap<Integer, String>(
                LEN, 0.75f, true);
        for (int i = 0; i < LEN; i++) {
            map.put(i, new String(">" + i));
        }
        
        for (Map.Entry<Integer, String> entry : map.entrySet()) {
            System.err.println("=" + entry.getValue());
            if(entry.getKey() == 2) {
                break;
            }
        }
        
        for (Map.Entry<Integer, String> entry : map.entrySet()) {
            System.err.println("=" + entry.getValue());
            if(entry.getKey() == 2) {
                break;
            }
        }     
    }
}


Output:
Цитата

=>0
=>1
=>2
=>0 // по идее тут я должен был продолжить итерировать с 3
=>1
=>2



--------------------
Открыта вакансия Junior Java Developer'а в нашем лондонском офисе, подробнее можно узнать здесь
PM MAIL MSN   Вверх
LSD
Дата 28.4.2008, 11:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15718
Регистрация: 24.3.2004
Где: Dublin

Репутация: 210
Всего: 538



Цитата(Royan @  28.4.2008,  01:35 Найти цитируемый пост)
по идее тут я должен был продолжить итерировать с 3

Клево придумано smile В одном методе, мы проитерировали коллекцию до середины, в другом до проитерировали с середины до конца. А дальше ничего уже больше не итерируем, т.к. дошли до конца. Так? smile

То что ты хочешь, реализуется так:
Код

import java.util.*;

public class Test
{
  public static void main(String[] args) throws Exception
  {
    final int LEN = 10;
    LinkedHashMap<Integer, String> map = new LinkedHashMap<Integer, String>(LEN, 0.75f, true);
    for(int i = 0; i < LEN; i++)
      map.put(i, "(" + i + ")");

    Iterator<Map.Entry<Integer, String>> iterator = map.entrySet().iterator();

    while(iterator.hasNext())
    {
      Map.Entry<Integer, String> entry = iterator.next();
      System.out.println("=" + entry.getValue());
      if(entry.getKey() == 2)
        break;
    }

    while(iterator.hasNext())
    {
      Map.Entry<Integer, String> entry = iterator.next();
      System.out.println("=" + entry.getValue());
      if(entry.getKey() == 2)
        break;
    }
  }
}


Есть такая штука ListIterator, вот он позволяет указывать с какого места начати итерацию, и позволяет итерировать как вперед, так и назад. Но существует, только для List.

P.S. И не пиши new String(">" + i) это совершенно избыточный код, приводящий к созданию лишних объектов. Вполне достаточно ">" + i.


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
javastic
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0565 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.