Обычная версия
Java форум JavaTalks
форум программистов

Поиск   Пользователи   Группы   Регистрация 
 Профиль   Личные сообщения 

 Вход 

Сортировка миллиона строк
Список форумов
 ->  Коллекции (Java Collection Framework)


На страницу 1, 2, 3  След. 
Начать новую тему 
Предыдущая тема :: Следующая тема  
Автор Сообщение
John77 : 3
Новичок

СообщениеОкт 16, 2011 20:43 
Ответить с цитатой
Здравствуйте. Тут в теме про вопросы на собеседовании выкладывали задачу на скорость сортировки:

5. Нужно остсортировать миллион строк (java.lang.String). Что будет быстрее: добавить их в TreeSet, добавить их в коллецию и потом отсортировать, что-то другое?

Подскажите что будет быстрее?
К началу Посмотреть профиль Отправить личное сообщение
Jean : 1992
JavaTalks Team Member
Откуда: Санкт-Петербург

СообщениеОкт 17, 2011 3:31 
Ответить с цитатой
Сортировка коллекции, если это quick sort (кажется именно такой алгоритм реализован во встроенных коллекциях в Java), выполняется за NlogN.
Добавление элемента в TreeSet стоит logN, таких элементов - N. Очевидно, что сложность та же.

Я бы предложил использовать многопоточность - разбиваем весь миллион на несколько подсписков (по числу процессоров с учетом гипертрединга и т.д.) и выполняем одновременно. Затем, один поток собирает все отсортированные подсписки и сортирует их между собой.
_________________
Всякое решение плодит новые проблемы
К началу Посмотреть профиль Отправить личное сообщение
OneHalf : 103
Новичок

СообщениеОкт 17, 2011 8:03 
Ответить с цитатой
Не думаю, что сложность та же. Ведь когда добавляются элементы, то Log N надо считать от текущего значения N, а не от того, до которого коллекция должна вырасти.
К началу Посмотреть профиль Отправить личное сообщение
stolzen : 422
Бывалый
Откуда: Нижний Новгород

СообщениеОкт 17, 2011 10:26 
Ответить с цитатой
Сложность в обоих случаях N log N, но фактически просто сортировка должна быть быстрее. А почему бы просто не проверить?
К началу Посмотреть профиль Отправить личное сообщение Посетить сайт автора
Jean : 1992
JavaTalks Team Member
Откуда: Санкт-Петербург

СообщениеОкт 19, 2011 1:37 
Ответить с цитатой
stolzen писал(а):
Сложность в обоих случаях N log N, но фактически просто сортировка должна быть быстрее. А почему бы просто не проверить?

Если сложность описывается одной формулой, то как просто сортировка может быть быстрее?
Проверять желательно уже после того, как получатся какие-нибудь предположения. Особенно в данном случае, когда анализ относительно простой.
_________________
Всякое решение плодит новые проблемы
К началу Посмотреть профиль Отправить личное сообщение
Jean : 1992
JavaTalks Team Member
Откуда: Санкт-Петербург

СообщениеОкт 19, 2011 1:52 
Ответить с цитатой
OneHalf писал(а):
Не думаю, что сложность та же. Ведь когда добавляются элементы, то Log N надо считать от текущего значения N, а не от того, до которого коллекция должна вырасти.

Верно, но это записывается формулой Sum (log i), где i = от 1 до N. А сама эта формула приблизительно равна (NlogN - 1.5). То есть сложность все-таки NlogN.
_________________
Всякое решение плодит новые проблемы
К началу Посмотреть профиль Отправить личное сообщение
stolzen : 422
Бывалый
Откуда: Нижний Новгород

СообщениеОкт 19, 2011 8:15 
Ответить с цитатой
Код:
public static void main(String[] args) {
   
    final String[] strings = prepareStrings();
   
    long forSet = timeIt(new Lambda() {
        @Override
        public void apply() {
            Set<String> set = new TreeSet<String>();
           
            for (String str : strings) {
                set.add(str);
            }
        }
    });
   
    System.out.println("red-black tree: " + forSet);
   
    final List<String> list = new ArrayList<String>(Arrays.asList(strings));
   
    long forList = timeIt(new Lambda() {
        @Override
        public void apply() {
            Collections.sort(list);
        }
    });
   
    System.out.println("merge stable sort: " + forList);
}

private static String[] prepareStrings() {
    int len = 1000000;
    final String[] strings = new String[len];
   
    for (int i = 0; i < len; ++i) {
        strings[i] = UUID.randomUUID().toString();
    }
    return strings;
}

static long timeIt(Lambda lambda) {
    long start = System.nanoTime();
    lambda.apply();
    long end = System.nanoTime();
    return end - start;
}


Вывод:
red-black tree: 1920975506
merge stable sort: 1257984920


Последний раз редактировалось: stolzen (Окт 20, 2011 8:20), всего редактировалось 1 раз
К началу Посмотреть профиль Отправить личное сообщение Посетить сайт автора
John77 : 3
Новичок

СообщениеОкт 19, 2011 10:42 
Ответить с цитатой
Всем спасибо за ответы!

Цитата:
Думаю тут еще дело в том, что для TreeSet внутри при возрастании кол-ва элементов постоянно идет перемещение элементов в новый массив

у treeset внутри не массив а бинарное дерево. о каком перемещении идет речь?
К началу Посмотреть профиль Отправить личное сообщение
stolzen : 422
Бывалый
Откуда: Нижний Новгород

СообщениеОкт 19, 2011 20:31 
Ответить с цитатой
Дезинформация

Почистил )


Последний раз редактировалось: stolzen (Окт 20, 2011 8:20), всего редактировалось 1 раз
К началу Посмотреть профиль Отправить личное сообщение Посетить сайт автора
kamre : 329
Бывалый

СообщениеОкт 19, 2011 20:51 
Ответить с цитатой
stolzen писал(а):
думаю, что и TreeSet внутри имеет что-то похожее - только элементы в массиве упорядочены и добавление туда происходит по правилам черно-красного дерева.

Весьма странное предположение Smile
К началу Посмотреть профиль Отправить личное сообщение
John77 : 3
Новичок

СообщениеОкт 19, 2011 22:42 
Ответить с цитатой
stolzen писал(а):
John77 писал(а):
у treeset внутри не массив а бинарное дерево. о каком перемещении идет речь?


Ну а сами данные TreeSet (правильнее сказать TreeMap) где-то же должен хранить. Они хранятся в массиве. Так как зараннее не известно, сколько элементов будет в множестве, размер массива постепенно увеличивается с ростом кол-ва элементов. Сначала выделяется память под n елементов, когда кол-во элементов достигает n, создается новый массив размера, например, 2n, в который копируются все элементы со старого. По крайней мере так устроен ArrayList, думаю, что и TreeSet внутри имеет что-то похожее - только элементы в массиве упорядочены и добавление туда происходит по правилам черно-красного дерева.


нет массива а есть объекты Entry в которых есть ссылки (left,right,parent) на такие же Entry.

Интересно почему добавление в TreeSet занимает почти в 2 раза больше времени чем сортировка коллекции, ведь сложность и у того и у того как мы выяснили одинаковая - NlogN
К началу Посмотреть профиль Отправить личное сообщение
stolzen : 422
Бывалый
Откуда: Нижний Новгород

СообщениеОкт 20, 2011 8:18 
Ответить с цитатой
Да действительно, перепутал с кучей.
Надо было хоть сурц глянуть перед предположениями (facepalm)
К началу Посмотреть профиль Отправить личное сообщение Посетить сайт автора
Jean : 1992
JavaTalks Team Member
Откуда: Санкт-Петербург

СообщениеОкт 20, 2011 8:23 
Ответить с цитатой
John77 писал(а):
stolzen писал(а):
John77 писал(а):
у treeset внутри не массив а бинарное дерево. о каком перемещении идет речь?


Ну а сами данные TreeSet (правильнее сказать TreeMap) где-то же должен хранить. Они хранятся в массиве. Так как зараннее не известно, сколько элементов будет в множестве, размер массива постепенно увеличивается с ростом кол-ва элементов. Сначала выделяется память под n елементов, когда кол-во элементов достигает n, создается новый массив размера, например, 2n, в который копируются все элементы со старого. По крайней мере так устроен ArrayList, думаю, что и TreeSet внутри имеет что-то похожее - только элементы в массиве упорядочены и добавление туда происходит по правилам черно-красного дерева.


нет массива а есть объекты Entry в которых есть ссылки (left,right,parent) на такие же Entry.

Интересно почему добавление в TreeSet занимает почти в 2 раза больше времени чем сортировка коллекции, ведь сложность и у того и у того как мы выяснили одинаковая - NlogN


Потому что есть накладные расходы на создание энтри в мапе, бакетов для мапы, на переупорядочивание данных в новых бакетах и пр. Для того, чтобы мерить перфоманс, нужно создавать мапу сразу на 2 млн элементов либо, что надежнее, первый раз прогонять "вхолостую", а замеры начинать только со второго захода.
_________________
Всякое решение плодит новые проблемы
К началу Посмотреть профиль Отправить личное сообщение
stolzen : 422
Бывалый
Откуда: Нижний Новгород

СообщениеОкт 20, 2011 8:31 
Ответить с цитатой
Jean писал(а):
Потому что есть накладные расходы на создание энтри в мапе, бакетов для мапы, на переупорядочивание данных в новых бакетах и пр. Для того, чтобы мерить перфоманс, нужно создавать мапу сразу на 2 млн элементов либо, что надежнее, первый раз прогонять "вхолостую", а замеры начинать только со второго захода.


А пример можно?

(а если нужно _просто_ отсортировать, каждый раз вхолостую прогонять?)

Цитата:
Для того, чтобы мерить перфоманс, нужно создавать мапу сразу на 2 млн элементов

Кстати не нашел способа как этого добиться для TreeMap. Видимо (как меня уже поправили) потому что там ссылки, а не массив.
К началу Посмотреть профиль Отправить личное сообщение Посетить сайт автора
Jean : 1992
JavaTalks Team Member
Откуда: Санкт-Петербург

СообщениеОкт 20, 2011 11:22 
Ответить с цитатой
stolzen писал(а):
Jean писал(а):
Потому что есть накладные расходы на создание энтри в мапе, бакетов для мапы, на переупорядочивание данных в новых бакетах и пр. Для того, чтобы мерить перфоманс, нужно создавать мапу сразу на 2 млн элементов либо, что надежнее, первый раз прогонять "вхолостую", а замеры начинать только со второго захода.


А пример можно?

(а если нужно _просто_ отсортировать, каждый раз вхолостую прогонять?)

Цитата:
Для того, чтобы мерить перфоманс, нужно создавать мапу сразу на 2 млн элементов

Кстати не нашел способа как этого добиться для TreeMap. Видимо (как меня уже поправили) потому что там ссылки, а не массив.


Да, вы правы, для TreeMap этого всего нельзя сделать - нельзя задать ей размер и т.д.
Если нужно просто сортировать, то нужно выбирать оптимальный способ.
Все-таки при использовании TreeMap создаются Entry. Для миллиона строк будет создано миллион Entry. Хотя сама по себе операция дешевая, она все-таки напрочь отсутствует для простой сортировки. После каждой вставки в TreeSet (что тоже самое, что TreeMap) происходит балансировка дерева (что должно быть самым дорогим). Плюс при вставке в TreeSet происходят тьма разных проверок дополнительных к непосредственному compare.
Вот, если бы исключить эти ребалансировку и все-таки начать измерения вемени со второго раза, результаты были бы вернее.

Возьметесь проверить?
_________________
Всякое решение плодит новые проблемы
К началу Посмотреть профиль Отправить личное сообщение
 
Начать новую тему  Ответить на тему
Страница 1 из 3
На страницу 1, 2, 3  След.
Список форумов
 -> Коллекции (Java Collection Framework)


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


Java and all Java-related trademarks and logos are trademarks or registered trademarks of Oracle Corporation in the United States and other countries.
Это сайт не относится к фирме Oracle Corporation и не поддерживается ею.

© 2006-2010 www.javatalks.ru: форум java программистов
Используется скрипт phpBB © 2001, 2010 phpBB Group

Хостинг от bizname.ru