Задать вопрос
  • Какие преимущества у NoSQL?

    leahch
    @leahch
    3D специалист. Dолго, Dорого, Dерьмово.
    Вообще-то noSQL бывает сильно разный, заточенный под совершенно разные задачи, которые очень плохо натягиваются на обычный SQL с его транзакциями, логированием, индексацией, и системой запросов.

    Приведу несколько примеров, где noSQL выигрывает в разы. Причем, во всех задачах можно извратиться и на обычном SQL.

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

    Задача сбора и агрегации (обыкновенные счетчики) - можно взять и SQL, но обычно тут не нужны транзакции и связанные с этим накладные расходы, поэтому берем тарантул, редис или каффака.

    Задача полнотекстового поиска по документам - решать ее на SQL, не очень приятное занятие, возьмем например солр/эластик/сфинкс.

    Задача хранения объектов - на SQL ее тоже решать часть не с руки, особенно, когда структура самих объектов сильно расширяется. Возьмем монгу.

    Задача хранения логов временных рядов с агрегацией - тут с SQL просто швах! Возьмем influxdb или clickhouse.

    При этом, у SQL очень часто есть серьезный недостаток в масштабировании, что легко решается в noSQL.

    Ах, да, очень часто ставят рядом и SQL и noSQL, и данные разбрасывают в разные базы по конкретным задачам.
    Ответ написан
    2 комментария
  • Какие преимущества у NoSQL?

    Если кратко, то NoSQL - это все то, что не SQL. То, что не подходит под нотацию реляционной модели.

    NoSQL решение может быть выгодно, когда нет необходимости следовать определеной схеме(таблицы, связи, типы данных и тд). Мы не думаем о предварительной настройке структуры, нормализации отношений; данные могут быть легче изменены, мигрированы и тд. Но взамен там появляются проблемы с ACID и прочими вещами, которые легче соблюдать в SQL - решениях.
    Ответ написан
    Комментировать
  • Что именно можно хранить в NOSQL базах данных?

    2ord
    @2ord
    NoSQL бывают разных видов:
    • ключ-значение
      Могут применяться для получения сериализованного объекта по строковому ключу. Могут присутствовать операции над списками, счетчики и пр. Memcached, Redis, Tarantool - работают полностью в RAM, поэтому особо не разгуляться.
      Есть персистентные: RocksDB, BerkeleyDB, ...
    • Графовые
      Удобно использовать когда в случаях, если в SQL запросах есть много JOIN и это все медленно работает из-за множества взаимосвязанных моделей
    • документо-ориентированные
      Когда есть необходимость работать со сложными структурами данных и в них нужно обновлять какие-то поля.
      Saboteur в целом описал преимущества.
      Но не испробовав тип JSON в РСУБД, я бы не стал сходу менять на документо-ориентированную.

    • колоночные
      Хороши для аналитических запросов
      https://m.habr.com/ru/post/95181/


    https://database.guide/nosql-database-types/
    Ответ написан
    Комментировать
  • Что именно можно хранить в NOSQL базах данных?

    saboteur_kiev
    @saboteur_kiev
    software engineer
    Все можно хранить. Но nosql базы бывают разные, заточенные под разные задачи.
    Надо уточнять для чего вам база.
    memcached, например, тоже можно сказать что это Nosql база. Используется для ускорения доступа.

    А mongodb это скорее объекты, а не документы.

    Например, вам нужно хранить такие поля
    имя, фамилия, телефон
    имя, адрес
    фамилия, инициалы, год рождения
    телефон, адрес, описание

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

    А в mongodb,например, можно просто хранить объекты как есть:
    Имя: Вася, Фамилия: Пупкин, телефон 02
    Имя: Петя, адрес: "Останкино, 1"
    Имя: Вера, инициалы: "В.Б.", год рождения: нескажу
    телефон: "красненький", адрес: "Останкино, 1", описание: "что-то где-то"

    И каждый объект хранится ровно с теми полями, которые в нем есть.
    При этом поля могут быть разного типа.
    При этом можно нормально пользоваться запросами и разными функциями.

    Да, тут нет joins, зато монго оптимизирована для работы с подобным и размеры коллекций ее не слишком будут смущать.
    Ответ написан
    6 комментариев
  • "localstorage" или cookie?

    Apathetic
    @Apathetic
    Frontend
    На самом деле всё просто. Куки - для сервера, локалсторадж - для клиента. Если информация, которую вы собираетесь хранить, нужна только на клиенте - нет никакого смысла в том, чтобы гонять куки туда-сюда при каждом запросе к серверу. Если какая-то информация нужна постоянно серверу - используйте куки.
    Кроме того, а куки 4кб выделяется, на localStorage - 5 мб.
    Подводных камней нет никаких, если нет необходимости поддерживать старые ие - используйте смело. caniuse.com/#search=localstorage

    Что касается отключения: пользователь может превентивно запретить использование localStorage. На практике с таким не сталкивался, думаю, что целенаправленно этим занимаются еще реже, чем отключением cookies.
    Ответ написан
    5 комментариев
  • Что за фигурные скобки в Java?

    Vamp
    @Vamp
    Эта конструкция называется блоком статической инициализации. Есть ещё точно такой же блок динамической инициализации, только без ключевого слова static.

    Блоки инициализации нужны для задания начальных значений полям класса.
    class Initable2 {
        static int staticNonFinal;
    
        public static void main(String[] args) {
            System.out.println(staticNonFinal);
        }
    }

    Данный пример выведет ноль, хотя переменной staticNonFinal не присваивалось никакое значение. Java гарантирует, что любые поля класса будут проинициализированы "нулевым" значением. То есть компилятор неявно вставляет в класс блок статической инициализации, в котором переменной staticNonFinal присваивается ноль.

    class Initable2 {
        static int staticNonFinal;
    
        // Вот этот блок будет добавлен к
        // вашему классу во время компиляции.
        static {
            staticNonFinal = 0;
        }
    
        public static void main(String[] args) {
            System.out.println(staticNonFinal);
        }
    }


    Разумеется, вы можете инициализировать переменные своими значениями:
    class Initable2 {
        static int staticNonFinal = 42;
    
        static String a = "hello";
    
        static Cache<String, Integer> b = CacheBuilder.newBuilder()
            .maximumSize(100)
            .expireAfterWrite(10, TimeUnit.MINUTES)
            .build();
    }

    И тогда компилятор в блоке инициализации будет подставлять ваши значения вместо нулей:
    class Initable2 {
        static int staticNonFinal;
    
        static String a;
    
        static Cache<String, Integer> b;
    
        static {
            staticNonFinal = 42;
            a = "hello";
            b = CacheBuilder.newBuilder()
                .maximumSize(100)
                .expireAfterWrite(10, TimeUnit.MINUTES)
                .build();
        }
    }

    А если вашей переменной требуется какая-то сложная инициализация, которую одной строкой не представить (как в примере с Cache), то тогда вам придется написать блок инициализации явным образом вручную:
    class Initable2 {
        static int staticNonFinal = 42;
    
        static Map<Integer, String> statusCodes = new HashMap<>();
    
        static {
            statusCodes.put(200, "OK");
            statusCodes.put(404, "Not Found");
            statusCodes.put(418, "I'm a teapot");
        }
    }

    И тогда компилятор сгенерирует вам такой код:
    class Initable2 {
        static int staticNonFinal;
    
        static Map<Integer, String> statusCodes;
    
        static {
            staticNonFinal = 42;
            statusCodes = new HashMap<>()
            statusCodes.put(200, "OK");
            statusCodes.put(404, "Not Found");
            statusCodes.put(418, "I'm a teapot");
        }
    }


    Точно таким же способом инициализируются и нестатические поля при помощи блока динамической инициализации (перед таким блоком отсутствует ключевое слово static и выглядит как просто фигурные скобки в теле класса). Каждый раз при создании объекта класса сначала выполняется блок динамической инициализации, а затем конструктор. Именно в таком порядке. Блок статической инициализации выполняется один раз при загрузке класса в память.

    Блоки динамической инициализации редко используются программистами, так как проще всего сделать "инициализацию" в конструкторе (в кавычках, потому что формальная инициализация уже была выполнена перед запуском конструктора и конструктор просто переписывает уже инициализированное значение своим, поэтому более точным термином здесь будет переприсваивание). Но блоки статической инициализации используются довольно часто, так как статических конструкторов не существует.

    Вот эти все блоки инициализации были придуманы создателями языка java чтобы исключить целый класс лютых ошибок, связанных с доступом к неинициализированным переменным, характерный для языков си и си++.
    Ответ написан
    Комментировать
  • Как на самом деле работает параллелизм?

    Vamp
    @Vamp
    Вопрос 1. Два конвейера позволяют только сократить накладные расходы на context switch. Параллелизм это не увеличивает, так как вычислительное ядро по-прежнему одно.

    Вопрос 2. Верно. Разделите понятия процесс и поток. Думайте о процессе как о контейнере для потоков, а не как об активной сущности, которая исполняет код. В каждом процессе есть как минимум 1 поток. Все без исключения программы стартуют как однопоточный процесс, который имеет возможность превратиться в многопоточный, заспавнив ещё потоков. Ну и, соответственно, ОС шедулит потоки, а не процессы.

    Вопрос 3. Нет. Процессор сам подгружает инструкции из кеша/основной памяти. Потоки не совершают никаких дополнительных действий для этого. Всё происходит прозрачно для потока.

    Вопрос 4. Kernelspace и userspace потоки отличаются только тем, в каких кольцах они исполняются. Kernel потоки исполняются в привилегированных кольцах, а user потоки в непривилегированных. Во всём остальном эти потоки ничем друг от друга не отличаются. Кольца ограничивают набор процессорных инструкций и системных вызовов, которые поток может использовать. Например, чтение файла с диска - это привилегированная операция (так как требует прямого доступа к девайсу), поэтому когда обычный userspace поток хочет прочитать файл, ОС приостанавливает userspace поток и передаёт управление kernelspace потоку, у которого достаточно привилегий на выполнение данной операции.

    Кооперативную многозадачность можно сделать и самому. Концепция называется green threads. В языках программирования встречается уже готовая реализация грин тредов, только называется иначе: корутины (python), горутины (go), виртуальные потоки (java). Все они делают одно и то же - реализуют кооперативную многозадачность в userspace. При большом желании можно написать и свою реализацию грин тредов без использования уже готовых языковых инструментов. Хотя практического смысла в этом мало (кроме нарабатывания опыта).

    Вопрос 5. Думаю, ответ на этот вопрос очевиден из ответа на предыдущий.

    И всё же под "kernel" обычно подразумевают ядро ОС, а не ядро процессора (которое называют core, а не kernel). Единственный способ запустить поток в kernelspace - написать модуль/драйвер ядра. Обычные программы так не могут.

    Финальный вопрос. Правильно понимаете. Вот только "пошаговая стратегия" - это про многозадачность, а не про параллелизм. Процессор с одним ядром многозадачным быть может. Параллельным - нет.
    Ответ написан
    7 комментариев
  • Почему JIT транслирует код в байты, а не в биты?

    Sputterspark
    @Sputterspark
    JIT-компилятор транслирует код в машинные инструкции, а они меньше байта не бывают.
    Ответ написан
    Комментировать
  • Как и где найти грамотного персонального преподователя JAVA?

    Sputterspark
    @Sputterspark
    Нигде не найти. Нафига хорошему разработчику тратить своё драгоценное время на обучение непонятно кого?
    Ответ написан
    4 комментария
  • Меняют ли аннотации данные в коде?

    sergey-gornostaev
    @sergey-gornostaev Куратор тега Java
    Седой и строгий
    Сами по себе аннотации ничего не меняют. Если написать Member member = new Member() то поле firstName экземпляра member будет равно null, а не 30. Нужен какой-то ещё код, который обработает аннотации и в соответствии с ними выполнит какие-либо действия. Обычно обрабатывают аннотации фреймворки, компилятор или его плагины.
    Ответ написан
    2 комментария
  • Меняют ли аннотации данные в коде?

    @Akela_wolf
    Extreme Programmer
    Давайте по порядку.

    Что такое аннотация? Аннотация - это некоторые произвольные метаданные, которые программист может присоединить к некоторому объекту. И только. Данные, ничего кроме. Никакого поведения сама по себе аннотация не добавляет.

    То есть аннотация ничего не делает? Да, именно так. Сама по себе аннотация ничего не делает.

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

    Второй вид процессоров аннотаций работает во время выполнения программы. Через механизм рефлексии он анализирует аннотации, которые добавил программист, и выполняет логику в соответствии с аннотации и содержащимися в них даннми. Так, например, работает Spring, который в соответствии с аннотациями @Service, @Scope, @Autowired, @Controller и т.п. инициализирует компоненты приложения и запускает его в нужной конфигурации.

    У Эккеля написано неточно (либо это неточный перевод, такое тоже часто бывает). Переменные никакого значения не получают, получает значение поле в аннотации (аннотация в Java - это тоже объект и тоже имеет поля). А затем уже процессор аннотаций значение этого поля как-то использует (в приведенном примере - устанавливает соответствие с колонкой в таблице базы данных соответствующего типа и, при необходимости, создает её).

    У Шилдта написано корректнее - сами по себе аннотации никак семантику программы не затрагивают, для того чтобы они заработали требуется дополнительный код.
    Ответ написан
    1 комментарий
  • Простыми словами, чем отличаются UTC or GMT?

    bingo347
    @bingo347
    Crazy on performance...
    UTC - Universal Time Coordinated, универсальное координированное время.
    Стандарт регулирования времени с точностью до секунд или дробных частей секунд. Эталоном являются атомные часы. На основе UTC формируется время в разных часовых поясах.

    GMT - Greenwich Mean Time, среднее время по Гринвичу.
    По сути является усредненным за некоторый промежуток времени измерением времени по солнцу в определенной точке земли, а именно в обсерватории Гринвича, что недалеко от Лондона.

    От какого времени принято отталкиваться в программировании
    Делают и так и так, но лучше от UTC ибо стандарт и формально более точный, например учитывает високосные секунды именно в те дни, когда они были добавлены.
    Ответ написан
    Комментировать
  • В чем разница между List и LinkedList при объявлении списка?

    sergey-gornostaev
    @sergey-gornostaev Куратор тега Java
    Седой и строгий
    Разница в соблюдении LSP и ISP.
    Ответ написан
    3 комментария
  • Как Jit Компиляторы обнаружат недостижимой код и лишние проверки?

    mayton2019
    @mayton2019
    Bigdata Engineer
    Как Jit Компиляторы обнаружат недостижимой код и лишние проверки?

    Если мне не изменяет память, JIT компиллятор компилирует java-метод целиком. Переводя byte-code в машинный код для x86 например.

    А то что спрашивает автор - это задача основного компиллятора который язык Java переводит в байткод.

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

    ли Космические Лучи, в Ram попали, что тогда будет?

    Программисты 20-го века работали в условиях глючной памяти (когда были ЭВМ на лампах и на тразнисторах)
    и обрабатывали специальное прерывание типа "глюк в ячейке памяти".

    С точки зрения современной парадигмы разработки - это невозможно. Никакой прикладной
    программист не ставит себе задачу отслеживания целостности памяти. Это как-бы не его
    уровень. Мы предполагаем что память надежна и всегда корректна. А иначе ОС выпадает
    в синий экран и никаких принятий решения мы все равно не сделаем а облачные балансировщики
    примут свои решения когда хост выпадет из сети.

    В современной ОС также по дефолту считается что никакой хакер никогда не меняет
    память вашего процесса. Это - основа безопасности ОС и если хакер все таки что-то может
    менять - то это плохая ОС и плохая безопасность и надо что-то решать на уровне системной
    архитектуры и тем более прикладной программист здесь ничего не сможет сделать.

    Рассматривать такие случаи в топике Java - бесполезно и контр-продуктивно. Давайте
    их рассматривать в топиках инфо-беза и операционок.
    Ответ написан
    Комментировать
  • Зачем нужен байт-код?

    icelaba
    @icelaba
    Знаю и умею всё
    Особенность многих jit компиляторов в том что они умеют оптимизировать код на лету, используя статистику выполнения программы,
    например hotpath оптимизация считает количество попаданий в ту или иную часть программы, и генерит машинный код только для кусков кода где программа реально часто выполняется.
    Что это дает: за счет этого jit оптимизатор может разместить куски часто выполняющегося машинного кода очень близко друг к другу - так что они все целиком будут умещаться например в кэше процессора, и да - jit компилятор порой за счет этого обгоняет прекомпилированный машинный код.

    Есть еще куча оптимизаций например касающаяся языков которые поддерживают closures, как показывает практика большинство клозур используются в коде с одинаковыми переменными окружения, что позволяет не выполнять кучу работы по сохранению окружения и тп - а просто заинлайнить клозуру - другое дело что на этапе компиляции понять это невозможно, а вот на этапе выполнения сохранить hash окружения и если он не меняется то инлайнить код - легко

    Есть еще куча подобных оптимизаций которые реально помогают динамическим языкам работать почти наравне по скорости с С на некоторых задачах, яркий пример luajit

    И до кучи динамические языки зачастую невозможно заранее перенести в native код чтобы сам этот код не прератился в некорый интерпретатор байткода, вот хорошо про это написано:
    stackoverflow.com/questions/15626611/can-regular-j...

    (c# кстати нединамический поэтому для него насколько я помню была какая то тулзень для прекомпиляции в native код - но я уже лет сто ;-) не писал на c# поэтому точно не помню)
    Ответ написан
    4 комментария
  • Как сделать доступ к HashMap с других классов?

    sergey-gornostaev
    @sergey-gornostaev Куратор тега Java
    Седой и строгий
    А не надо делать её доступной во всех других классах, Сделайте классу, который её содержит, методы добавления и получения из неё данных.
    Ответ написан
    Комментировать
  • Что такое REST и RESTful api?

    DzodzikovAK
    @DzodzikovAK
    Java Developer
    REST - набор архитектурных принципов построения сервис-ориентированных систем.

    RESTful - прилагательное, употребляющееся по отношению к сервисам, которые следуют принципам REST.

    Вот здесь человек рассказывает (переводит), как определить, является ли ваш сервис RESTful и в какой степени:
    https://habrahabr.ru/post/319984/
    Ответ написан
    Комментировать
  • Кеширует ли java состояние hashmap или других коллекций?

    sergey-gornostaev
    @sergey-gornostaev Куратор тега Java
    Седой и строгий
    Перед входом в блок синхронизации или синхронизированный метод потоки обнуляют свои кэши, а при выходе сбрасывают кэш в память.

    Из JSR-133:
    But there is more to synchronization than mutual exclusion. Synchronization ensures that memory writes by a thread before or during a synchronized block are made visible in a predictable manner to other threads which synchronize on the same monitor. After we exit a synchronized block, we release the monitor, which has the effect of flushing the cache to main memory, so that writes made by this thread can be visible to other threads. Before we can enter a synchronized block, we acquire the monitor, which has the effect of invalidating the local processor cache so that variables will be reloaded from main memory. We will then be able to see all of the writes made visible by the previous release.
    Ответ написан
    4 комментария