Nano Hash - криптовалюты, майнинг, программирование

Сохранить число как текст ASCII в Java?

Наверное глупый вопрос, но вот в чем дело. Я читал этот вопрос:

Хранение 1 миллиона телефонных номеров

и принятый вопрос был тем, о чем я думал: используя попытку. В комментариях Мэтт Болл предположил:

Я думаю, что сохранение телефонных номеров в виде текста ASCII и сжатие — очень разумное предложение

Проблема: как мне это сделать в Java? А текст ASCII означает строку?

09.05.2011

Ответы:


1

Для хранения в памяти, как указано в вопросе:

ByteArrayOutputStream baos = new ByteArrayOutputStream();
OutputStreamWriter out = new OutputStreamWriter(
    new GZIPOutputStream(baos), "US-ASCII");
for(String number : numbers){
    out.write(number);
    out.write('\n');
}
byte[] data = baos.toByteArray();

Но, как заметил Пит: это может быть полезно для эффективности использования памяти, но впоследствии вы не можете ничего сделать с данными, так что это не очень полезно.

09.05.2011
  • Спасибо. Этот вопрос на собеседовании вывел меня из себя. 09.05.2011
  • Если порядок не имеет значения, я бы сначала отсортировал числа, так как они будут сжиматься намного лучше, поскольку каждое число будет почти таким же, как и предыдущее. 09.05.2011

  • 2

    Да, ASCII в данном случае означает строки. Вы можете хранить сжатые данные в Java, используя файл java. util.zip.GZIPOutputStream.

    09.05.2011
  • Я знаю, но это было связано с контекстом вопроса. Цифры имеют то же значение, что и в ASCII, если только мы не говорим об арабских цифрах. 09.05.2011
  • ASCII подразумевает один байт на символ, строки Java используют два. А обычные числа ASCII являются арабскими числами... 09.05.2011
  • Хорошо, я должен был сказать «арабско-индийский», «расширенный арабско-индийский» или «восточно-арабский». Эти числа не похожи на те, которые мы используем в западном мире, и они не входят в таблицу ASCII. Да, два байта в памяти для символов Java, но вы не будете записывать два байта, если записываете числа в файл, если не укажете нечетную кодировку. 09.05.2011

  • 3

    В ответ на подразумеваемый, но другой вопрос;

    В: У вас есть 1 миллиард телефонных номеров, и вам нужно отправлять их через соединение с низкой пропускной способностью. Вам нужно только отправить, находится ли номер телефона в коллекции или нет. (Другая информация не требуется)

    О: Это общий подход.

    • Сначала отсортируйте список, если он еще не отсортирован.
    • Из наименьшего числа найдите области непрерывных чисел. Пришлите стартовый регион и телефоны какие заняты. Это может быть сохранено в виде набора битов (1 бит на возможный номер). Отправляйте номер телефона в начале и набор битов всякий раз, когда разрыв превышает некоторый порог.
    • Запишите поток в сжатый набор данных.
    • Протестируйте это, чтобы сравнить с простой отправкой всех номеров.

    Вы можете использовать строки в отсортированном TreeMap. Один миллион номеров - это не так уж и много, и он займет около 64 МБ. Не вижу необходимости в более сложном решении.

    Последняя версия Java может эффективно хранить текст ASCII, используя byte[] вместо char[], однако накладные расходы вашей структуры данных, вероятно, будут больше.

    Если вам нужно сохранить номера телефонов в качестве ключа, вы можете хранить их с предположением, что большие диапазоны будут непрерывными. Таким образом, вы можете хранить их как

    NavigableMap<String, PhoneDetails[]>
    

    В этой структуре ключ будет определять начало диапазона, и у вас может быть информация о телефоне для каждого номера. Это может быть не намного больше, чем ссылка на PhoneDetails (что является минимумом).

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


    Многое зависит от того, что вы хотите делать с данными и почему они вообще у вас в памяти.

    Вы можете использовать DeflatorOutputStream для ByteArrayOutputStream, который будет очень маленьким, но не очень полезным.

    Я предлагаю использовать DeflatorOutputStream, так как он легче/быстрее/меньше, чем GZIPOutputStream.

    09.05.2011
  • Я подозреваю, что если бы вопрос был задан в Google, то это был бы 1 миллиард, а не 1 миллион именно по этой причине. И я почти уверен, что TreeMap of Strings будет иметь гораздо больше накладных расходов (TreeMap не является структурой данных с эффективным использованием памяти). 09.05.2011
  • Если бы вопрос был существенно другим, я бы дал другой ответ. Хотя TreeMap не очень эффективен, необходимость распаковывать все данные и анализировать каждый раз, когда вы хотите получить число, была бы неудобной. Многое зависит от того, что вы хотите делать с данными. Я сомневаюсь, что вы поместите 1 миллиард телефонных номеров в единую базу данных. 09.05.2011
  • Это вопрос из собеседования в Google (очевидно). 09.05.2011
  • @dierre, некоторые интервьюеры предпочитают теоретические ответы, а некоторые предпочитают ответы из реального мира. Вы должны решить, какой ответ они ищут, или найти способ дать оба. Часто самый быстрый/самый эффективный способ сделать то, что вам на самом деле не нужно делать, это; не делай все ;) 09.05.2011

  • 4

    Строки Java по умолчанию имеют кодировку UTF-8, вам необходимо измените кодировку, если вы хотите управлять текстом ASCII.

    09.05.2011
  • -1: Хотя внутренняя кодировка не указана в спецификации Java, API подразумевает UTF-16, и почти все реализации также используют ее внутри. UTF-8 используется только для литералов в файлах классов. 09.05.2011
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..