Форум программистов, компьютерный форум, киберфорум
hw_wired
Войти
Регистрация
Восстановить пароль
Оценить эту запись

Чем отличаются HashMap и Hashtable в Java

Запись от hw_wired размещена 24.01.2025 в 19:48
Показов 1396 Комментарии 0
Метки java

Нажмите на изображение для увеличения
Название: cd385fc5-75c8-4cae-9675-6290a1e12a30.png
Просмотров: 57
Размер:	2.81 Мб
ID:	9372
В мире разработки на Java существует множество инструментов для работы с коллекциями данных, и среди них особое место занимают структуры данных для хранения пар ключ-значение. HashMap и Hashtable являются двумя фундаментальными реализациями интерфейса Map в Java, предоставляющими механизм хранения и доступа к данным по уникальным ключам. Несмотря на схожесть их базовой функциональности, эти классы имеют существенные различия, которые могут значительно повлиять на производительность и надежность приложения.

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

В современной разработке на Java необходимо четко понимать, какая из этих реализаций лучше подходит для конкретного сценария использования. Знание нюансов работы HashMap и Hashtable, их сильных и слабых сторон позволяет разработчикам создавать более эффективный и надежный код. В данной статье мы подробно рассмотрим ключевые различия между этими структурами данных, проанализируем их особенности и предоставим практические рекомендации по их использованию в различных ситуациях.

Основные отличия



Одним из ключевых различий между HashMap и Hashtable является подход к синхронизации, который фундаментально влияет на их производительность и применимость в различных сценариях разработки. Hashtable является синхронизированной структурой данных, что означает, что все операции чтения и записи автоматически синхронизируются. Каждый метод в Hashtable помечен ключевым словом synchronized, обеспечивая потокобезопасность при работе с данными. Например, когда один поток выполняет операцию записи в Hashtable, другие потоки не могут одновременно получить доступ к этой структуре данных, что предотвращает возможные конфликты и обеспечивает целостность данных.

HashMap, напротив, не обеспечивает автоматическую синхронизацию операций. Это означает, что операции чтения и записи выполняются без дополнительных механизмов блокировки, что делает HashMap более эффективной в однопоточных приложениях. При необходимости использования HashMap в многопоточной среде разработчики должны самостоятельно обеспечивать синхронизацию, используя внешние механизмы блокировки или обертки, такие как Collections.synchronizedMap(). Рассмотрим пример кода, демонстрирующий различия в создании синхронизированной и несинхронизированной карты:

Java
1
2
3
4
5
6
7
8
// Создание несинхронизированной HashMap
Map<String, Integer> hashMap = new HashMap<>();
 
// Создание синхронизированной обертки над HashMap
Map<String, Integer> synchronizedMap = Collections.synchronizedMap(new HashMap<>());
 
// Создание Hashtable (синхронизирована изначально)
Hashtable<String, Integer> hashtable = new Hashtable<>();
Другим существенным отличием является обработка null-значений. HashMap допускает использование null как в качестве ключей, так и в качестве значений. Это предоставляет большую гибкость при работе с данными, особенно в ситуациях, когда необходимо явно указать отсутствие значения. В HashMap можно хранить один null-ключ и любое количество null-значений. Напротив, Hashtable полностью запрещает использование null как для ключей, так и для значений. При попытке добавить null в Hashtable будет выброшено исключение NullPointerException.

Эти фундаментальные различия в подходах к синхронизации и обработке null-значений значительно влияют на производительность этих структур данных. HashMap обычно демонстрирует более высокую производительность в большинстве сценариев использования, особенно в однопоточных приложениях, благодаря отсутствию накладных расходов на синхронизацию. Кроме того, более гибкая политика обработки null-значений в HashMap делает её более удобной для использования в современных приложениях, где null может иметь особое семантическое значение.

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

Давайте рассмотрим пример, который наглядно демонстрирует различия в производительности между HashMap и Hashtable:

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Тестирование производительности
Map<Integer, String> hashMap = new HashMap<>();
Hashtable<Integer, String> hashtable = new Hashtable<>();
 
long startTime = System.nanoTime();
for (int i = 0; i < 1000000; i++) {
    hashMap.put(i, "value" + i);
}
long hashMapTime = System.nanoTime() - startTime;
 
startTime = System.nanoTime();
for (int i = 0; i < 1000000; i++) {
    hashtable.put(i, "value" + i);
}
long hashtableTime = System.nanoTime() - startTime;
В этом примере операции вставки в HashMap обычно выполняются значительно быстрее, чем аналогичные операции в Hashtable. Разница в производительности становится особенно заметной при большом количестве операций или при интенсивном доступе к данным из нескольких потоков. Основная причина такой разницы заключается в накладных расходах на синхронизацию в Hashtable.

Важно также отметить различия в обработке исключительных ситуаций. При работе с null-значениями HashMap демонстрирует более гибкое поведение. Рассмотрим следующий пример:

Java
1
2
3
4
5
6
7
HashMap<String, Integer> map = new HashMap<>();
map.put(null, 1);        // Допустимо
map.put("key", null);    // Допустимо
 
Hashtable<String, Integer> table = new Hashtable<>();
table.put(null, 1);      // Выбросит NullPointerException
table.put("key", null);  // Выбросит NullPointerException
Это различие в обработке null-значений является результатом исторического развития этих классов. Hashtable была создана как часть оригинальной коллекции классов Java и следует более строгим правилам обработки данных. HashMap, появившаяся позже, была разработана с учетом более современных требований к обработке данных и предоставляет большую гибкость в работе с null-значениями.

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

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

Какая разница между HashMap и HashTable?
какая разница между HashMap и HashTable?

Работа с свингами массивами hashmap hashtable,stack interface enum Swing Event Thread
Друзья всем привет,Из джава я знаю ООП ,работа с свингами массивами hashmap hashtable,stack interface enum Swing Event Thread. теперь пишите мне что...

Java HashMap
Структура данных - HashMap

Java hashmap iterator
Добрый вечер, помогите пожалуйста! В файле config.txt лежат ключи- значения a=2 b=3 c=4 xx=5. нужно чтобы получилось a=2 xx=5 те чтобы все пары...


Примеры использования



Выбор между HashMap и Hashtable во многом зависит от конкретных требований проекта и условий его выполнения. В однопоточных приложениях, где производительность является критически важным фактором, HashMap становится очевидным выбором. Рассмотрим практический пример использования HashMap в системе кэширования результатов вычислений:

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class ComputationCache {
    private final HashMap<String, Double> cache = new HashMap<>();
    
    public Double getResult(String input) {
        if (cache.containsKey(input)) {
            return cache.get(input);
        }
        Double result = performExpensiveCalculation(input);
        cache.put(input, result);
        return result;
    }
    
    private Double performExpensiveCalculation(String input) {
        // Сложные вычисления
        return Double.valueOf(input) * Math.PI;
    }
}
В данном случае использование HashMap оправдано отсутствием необходимости в синхронизации и требованием максимальной производительности. Система кэширования работает в однопоточном режиме, где дополнительные накладные расходы на синхронизацию были бы излишними. Более того, возможность хранения null-значений в HashMap может быть использована для кэширования отрицательных результатов вычислений.

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

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class SessionManager {
    private final Hashtable<String, UserSession> activeSessions = new Hashtable<>();
    
    public void createSession(String sessionId, UserSession session) {
        if (sessionId == null || session == null) {
            throw new IllegalArgumentException("Session ID and session object cannot be null");
        }
        activeSessions.put(sessionId, session);
    }
    
    public UserSession getSession(String sessionId) {
        return activeSessions.get(sessionId);
    }
    
    public void invalidateSession(String sessionId) {
        activeSessions.remove(sessionId);
    }
}
В этом примере использование Hashtable обеспечивает автоматическую синхронизацию всех операций с сессиями, что критически важно в контексте веб-приложения, где множество потоков может одновременно обращаться к данным сессий. Строгая проверка на null-значения в Hashtable также является преимуществом, так как помогает раньше обнаружить потенциальные проблемы с некорректными данными сессий.

При работе с конфигурационными данными, которые загружаются при старте приложения и редко изменяются, HashMap является предпочтительным выбором даже в многопоточной среде, поскольку операции чтения существенно преобладают над операциями записи:

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class ConfigurationManager {
    private static final Map<String, String> configuration = new HashMap<>();
    
    static {
        // Загрузка конфигурации при инициализации
        loadConfiguration();
    }
    
    private static void loadConfiguration() {
        configuration.put("database.url", "jdbc:mysql://localhost:3306/mydb");
        configuration.put("max.connections", "100");
        configuration.put("timeout.seconds", "30");
    }
    
    public static String getConfig(String key) {
        return configuration.get(key);
    }
}
В этом случае использование HashMap оправдано тем, что конфигурация загружается один раз при старте приложения, а затем только читается из разных потоков. Отсутствие синхронизации в HashMap не создает проблем, так как данные не модифицируются после инициализации.

Для реализации пула объектов в многопоточной среде часто требуется потокобезопасное хранилище, и здесь Hashtable может быть более предпочтительным выбором:

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class ObjectPool<T> {
    private final Hashtable<T, Boolean> pool = new Hashtable<>();
    private final ObjectFactory<T> factory;
    
    public ObjectPool(ObjectFactory<T> factory, int initialSize) {
        this.factory = factory;
        for (int i = 0; i < initialSize; i++) {
            T object = factory.createObject();
            pool.put(object, true);  // true означает, что объект доступен
        }
    }
    
    public T acquire() {
        for (Map.Entry<T, Boolean> entry : pool.entrySet()) {
            if (entry.getValue()) {
                pool.put(entry.getKey(), false);
                return entry.getKey();
            }
        }
        // Если нет доступных объектов, создаем новый
        T newObject = factory.createObject();
        pool.put(newObject, false);
        return newObject;
    }
    
    public void release(T object) {
        pool.put(object, true);
    }
}
В данном примере встроенная синхронизация Hashtable обеспечивает безопасное управление пулом объектов без необходимости реализации дополнительных механизмов синхронизации. Это особенно важно в условиях высокой конкуренции за ресурсы между потоками.

При разработке систем кэширования с ограниченным временем жизни объектов может быть полезен следующий паттерн с использованием HashMap:

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class TimedCache<K, V> {
    private final HashMap<K, CacheEntry<V>> cache = new HashMap<>();
    private final long timeToLiveMillis;
    
    public TimedCache(long timeToLiveMillis) {
        this.timeToLiveMillis = timeToLiveMillis;
    }
    
    public void put(K key, V value) {
        cache.put(key, new CacheEntry<>(value, System.currentTimeMillis()));
    }
    
    public V get(K key) {
        CacheEntry<V> entry = cache.get(key);
        if (entry == null) {
            return null;
        }
        
        if (System.currentTimeMillis() - entry.timestamp > timeToLiveMillis) {
            cache.remove(key);
            return null;
        }
        
        return entry.value;
    }
    
    private static class CacheEntry<V> {
        final V value;
        final long timestamp;
        
        CacheEntry(V value, long timestamp) {
            this.value = value;
            this.timestamp = timestamp;
        }
    }
}
В этой реализации HashMap используется для создания простого кэша с ограниченным временем жизни объектов. Отсутствие синхронизации позволяет достичь максимальной производительности в однопоточных сценариях, а возможность хранения null-значений может быть использована для индикации отсутствия данных в кэше.

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

Другие различия



Существенные различия между HashMap и Hashtable также проявляются в способах итерации по элементам коллекции. HashMap предоставляет более современные и удобные методы для обхода элементов, включая специальные представления для множества ключей, значений и пар ключ-значение. При использовании HashMap разработчики могут применять улучшенный цикл for-each и методы работы со стримами, появившиеся в Java 8, что делает код более читаемым и функциональным.

Механизмы итерации в Hashtable основаны на более старых подходах, унаследованных от ранних версий Java. При работе с Hashtable используется перечисление (Enumeration) – устаревший интерфейс, который менее удобен в использовании по сравнению с современным интерфейсом Iterator. Рассмотрим пример, демонстрирующий различия в итерации:

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// Итерация по HashMap с использованием современных методов
HashMap<String, Integer> hashMap = new HashMap<>();
for (Map.Entry<String, Integer> entry : hashMap.entrySet()) {
    String key = entry.getKey();
    Integer value = entry.getValue();
    // Обработка элементов
}
 
// Использование стримов с HashMap
hashMap.entrySet().stream()
    .filter(entry -> entry.getValue() > 100)
    .forEach(entry -> System.out.println(entry.getKey()));
 
// Классическая итерация по Hashtable
Hashtable<String, Integer> hashtable = new Hashtable<>();
Enumeration<String> keys = hashtable.keys();
while (keys.hasMoreElements()) {
    String key = keys.nextElement();
    Integer value = hashtable.get(key);
    // Обработка элементов
}
В контексте потокобезопасности Hashtable обеспечивает автоматическую синхронизацию на уровне всего объекта, что может привести к снижению производительности в сценариях с высокой конкуренцией за ресурсы. В отличие от этого, для обеспечения потокобезопасности HashMap разработчики могут использовать более гибкие механизмы синхронизации, такие как ConcurrentHashMap, который обеспечивает лучшую масштабируемость за счет сегментированной блокировки.

С точки зрения исходных интерфейсов, HashMap и Hashtable также имеют различия в иерархии наследования. HashMap реализует интерфейс Map и является частью коллекций Java Collections Framework, в то время как Hashtable была создана до появления этого фреймворка и была впоследствии адаптирована для соответствия его требованиям. Это историческое различие объясняет некоторые особенности в поведении и методах этих классов.

Еще одним важным различием является подход к обработке коллизий хэш-кодов. HashMap использует связанные списки и деревья (начиная с Java 8) для хранения элементов с одинаковым хэш-кодом, автоматически переключаясь между этими структурами данных в зависимости от количества коллизий. Это обеспечивает более эффективную работу при большом количестве элементов с одинаковым хэш-кодом. Hashtable использует более простой механизм разрешения коллизий, основанный только на связанных списках.

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

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

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Map<Integer, String> synchronizedHashMap = Collections.synchronizedMap(new HashMap<>());
Hashtable<Integer, String> hashtable = new Hashtable<>();
 
// Многопоточная запись в synchronized HashMap
synchronized(synchronizedHashMap) {
    for (Map.Entry<Integer, String> entry : synchronizedHashMap.entrySet()) {
        // Безопасная итерация
    }
}
 
// Итерация по Hashtable (синхронизация встроена)
for (Map.Entry<Integer, String> entry : hashtable.entrySet()) {
    // Автоматически синхронизированная итерация
}
С точки зрения обработки исключений, HashMap и Hashtable также демонстрируют различное поведение. Hashtable генерирует больше проверяемых исключений, что требует явной обработки потенциальных ошибок в коде. HashMap, напротив, чаще использует непроверяемые исключения, что делает код более лаконичным, но требует большей внимательности от разработчика. Кроме того, Hashtable предоставляет дополнительные методы для работы с устаревшими коллекциями, которые отсутствуют в HashMap, что может быть важно при поддержке legacy-кода.

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

Выбор между HashMap и Hashtable



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

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

При разработке новых приложений рекомендуется использовать HashMap в сочетании с современными механизмами синхронизации, такими как ConcurrentHashMap или явная синхронизация, когда это необходимо. Это обеспечит лучшую производительность и более гибкие возможности по управлению конкурентным доступом. Hashtable следует рассматривать как опцию только при необходимости поддержки устаревшего кода или при работе с системами, требующими строгой совместимости с более ранними версиями Java.

Работа с HashMap (Java)
Здравствуйте! Вопрос по созданию и работе HashMap. В HashMap должен быть ключ - номер месяца (i), а в ArrayList я планировал добавить все данные...

HashMap java доступ по значению
Есть доступ к значению через метод get() по ключу. А если нужно по значению, чтобы вывел ключ, который ему соответствует, как это сделать? Или мб...

Реализация delete в HashMap (java)
Метод delete должен удалять все элементы в мапе со значением value, но у меня не получается его реализовать,можете помочь?Весь код программы ниже ...

В чем отличия реализации TreeMap и HashMap?
подскажите, в чем отличия реализации TreeMap и HashMap???

Java HashMap, можно ли удалить элемент из списка, получаемого через get?
К примеру, имеется такая HashMap: private static Map&lt;Integer, List&lt;SkillEntry&gt;&gt; _cachedMap = new HashMap&lt;&gt;(); В неё внесены некие данные,...

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

Чем отличаются OpenJDK и JDK от Oracle?
Подскажите, чем отличаются OpenJDK и JDK от оракл? И какие еще JDK бывают? (Извиняйте за нубский вопрос)

Чем отличаются поля класса от полей объекта?
Здравствуйте! Объясните, пожалуйста, чем отличаются поля класса от полей объекта?

Коллекции List/ArrayList: чем отличаются и для чего нужны?
ОБЪЯСНИТЕ ЧТО ТАКОЕ LIST И ARRAYLIST,ЧЕМ ОНИ ОТЛИЧАЮТСЯ И ДЛЯ ЧЕГО НУЖНЫ ВОТ ЕЩЕ ДВА ЗАДАНИЯ,Я ЧТО-ТО ПОПЫТАЛСЯ СДЕЛАТЬ,НО ПОКА ЧТО НЕ СОВСЕМ...

Массив: Верно ли, что эти две последовательности отличаются не более, чем порядком следования членов?
Даны последовательности целых чисел X1, ....., Xn и Y1, ....., Yn . Верно ли, что эти две последовательности отличаются не более, чем порядком...

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

вычисляет количество элементов, которые отличаются по абсолютной величине от среднего арифметического всех элементов массива не более, чем на величину
public static void main(String args) { int b = 5, sred = 0, count = 0; Scanner scr = new...

Размещено в Без категории
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Всего комментариев 0
Комментарии
 
Новые блоги и статьи
Обработка массивов с помощью циклов в JavaScript
hw_wired 12.02.2025
Массивы в JavaScript - это упорядоченные наборы элементов, где каждый элемент имеет свой индекс, начиная с нуля. Они невероятно гибки в использовании, позволяя хранить данные любых типов - числа,. . .
Создание каталога и всех родительских каталогов с помощью Python
hw_wired 12.02.2025
Работа с файловой системой - одна из ключевых задач при разработке программного обеспечения. Особенно часто возникает потребность создавать каталоги для хранения файлов, логов, временных данных и. . .
Возврат файла к состоянию указанного коммита Git
hw_wired 12.02.2025
Git - распределенная система контроля версий, без которой сложно представить современную разработку программного обеспечения. Когда речь заходит о восстановлении файлов, Git предоставляет целый. . .
Сброс локальной ветки Git до состояния HEAD удаленного репозитория
hw_wired 12.02.2025
Работая в команде разработчиков, часто сталкиваешься с ситуацией, когда локальная версия кода существенно отличается от той, что находится в центральном репозитории. Такое расхождение может. . .
Запрет подсветки выделения текста с помощью CSS
hw_wired 12.02.2025
Выделение текста - одна из базовых возможностей взаимодействия пользователя с контентом на веб-странице. Однако в некоторых случаях стандартное поведение выделения может нарушать задуманный дизайн. . .
Выполнение другой программы из приложения Python
hw_wired 12.02.2025
При разработке современных приложений часто возникает потребность в запуске и взаимодействии с другими программами прямо из кода. Python предоставляет множество эффективных средств для выполнения. . .
Отличия между let и var в JavaScript
hw_wired 12.02.2025
Работа с переменными - один из основных моментов при написании программ на JavaScript. От правильного объявления и использования переменных зависит не только читаемость кода, но и его надежность, а. . .
Подключение файла JavaScript в других файлах JavaScript
hw_wired 12.02.2025
Самый современный и рекомендуемый способ подключения JavaScript-файлов - использование системы модулей ES6 с ключевыми словами 'import' и 'export'. Этот подход позволяет явно указывать зависимости. . .
Отмена изменений, не внесенных в индекс Git
hw_wired 12.02.2025
Управление изменениями в Git - одна из важнейших задач при разработке программного обеспечения. В процессе работы часто возникают ситуации, когда нужно отменить внесенные изменения, которые еще не. . .
Что такое px, dip, dp, and sp в Android
hw_wired 12.02.2025
При разработке мобильных приложений для Android одним из ключевых вызовов становится адаптация интерфейса под различные устройства. А ведь их действительно немало - от компактных смартфонов до. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru