Kotlin | Вопросы собесов
2.57K subscribers
28 photos
964 links
Download Telegram
🤔 Где создается композиция для вызова composable функции?

Композиция создаётся внутри функции setContent, которая задает точку входа для composable функций в Activity или Fragment. Она инициирует рендеринг интерфейса и управление состоянием.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3
🤔 Как в Ретрофите добавить возможность возвращать типы Rxjava?

Чтобы Retrofit мог возвращать Observable, Single, Maybe или Flowable из RxJava, нужно добавить RxJava Adapter.

🚩Добавление зависимости

В build.gradle.kts (Kotlin DSL)
dependencies {
implementation("com.squareup.retrofit2:adapter-rxjava3:2.9.0") // Адаптер для RxJava 3
implementation("io.reactivex.rxjava3:rxjava:3.1.8") // RxJava 3
}


🚩Подключение `RxJava3CallAdapterFactory`

Добавляем адаптер в Retrofit.Builder
val retrofit = Retrofit.Builder()
.baseUrl("https://api.example.com/")
.addConverterFactory(GsonConverterFactory.create()) // Преобразование JSON
.addCallAdapterFactory(RxJava3CallAdapterFactory.create()) // Поддержка RxJava
.build()


🚩Использование RxJava в API

Теперь можно возвращать RxJava-объекты вместо Call<>.
interface ApiService {
@GET("users/{id}")
fun getUser(@Path("id") userId: Int): Single<User>
}


Пример с Observable<> (несколько данных или обновления)
interface ApiService {
@GET("users")
fun getUsers(): Observable<List<User>>
}


Пример с Flowable<> (если нужен Backpressure)
interface ApiService {
@GET("posts")
fun getPosts(): Flowable<List<Post>>
}


🚩Подписка и обработка результата

Пример подписки в ViewModel (RxJava 3 + LiveData)
class UserViewModel(private val apiService: ApiService) : ViewModel() {

private val _userLiveData = MutableLiveData<User>()
val userLiveData: LiveData<User> = _userLiveData

fun fetchUser(userId: Int) {
apiService.getUser(userId)
.subscribeOn(Schedulers.io()) // Запрос в фоновом потоке
.observeOn(AndroidSchedulers.mainThread()) // Обновление UI в главном потоке
.subscribe({ user ->
_userLiveData.value = user
}, { error ->
Log.e("UserViewModel", "Ошибка загрузки", error)
})
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
🤔 Какие особенности отличия deep link от app link?

- Deep link: работает через схему URI (например, myapp://), требует настройки <intent-filter>.
- App link: использует HTTP/HTTPS ссылки и требует подтверждения владения доменом через файл assetlinks.json.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2
🤔 Как выглядит алгоритм запроса данных из двух таблиц и какая у него сложность?

Запрос данных из двух таблиц обычно выполняется с помощью операции объединения (JOIN) в SQL. Алгоритм и его сложность зависят от типа объединения, структуры данных и используемой базы данных.

🚩Пример запроса

Предположим, у нас есть две таблицы: employees и departments. Мы хотим получить список сотрудников вместе с их отделами.
SELECT employees.name, departments.name
FROM employees
INNER JOIN departments ON employees.department_id = departments.id;


🚩Алгоритмы выполнения JOIN

1⃣Nested Loop Join (Вложенные циклы)
Для каждой строки из первой таблицы выполняется поиск соответствующих строк во второй таблице.
for each row in employees:
for each row in departments:
if row.employees.department_id == row.departments.id:
yield (row.employees.name, row.departments.name)


2⃣Hash Join (Хеш-объединение)
Создается хеш-таблица для одной из таблиц на основе ключа соединения. Для каждой строки из другой таблицы проверяется наличие соответствующего ключа в хеш-таблице.
hash_table = {}
for each row in departments:
hash_table[row.id] = row.name
for each row in employees:
if row.department_id in hash_table:
yield (row.name, hash_table[row.department_id])


3⃣Sort-Merge Join (Сортировка и слияние)
Обе таблицы сортируются по ключу соединения, затем выполняется слияние отсортированных списков.
sorted_employees = sort(employees, key=lambda x: x.department_id)
sorted_departments = sort(departments, key=lambda x: x.id)
i, j = 0, 0
while i < len(sorted_employees) and j < len(sorted_departments):
if sorted_employees[i].department_id == sorted_departments[j].id:
yield (sorted_employees[i].name, sorted_departments[j].name)
i += 1
j += 1
elif sorted_employees[i].department_id < sorted_departments[j].id:
i += 1
else:
j += 1


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
💊3👍1
🤔 Какой архитектурный паттерн реализуется благодаря ViewModel?

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

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4🔥2
🤔 Можешь рассказать отличия и в каких случаях их использовать list set map?

В Kotlin есть три основных типа коллекций:
List — упорядоченный список элементов.
Set — множество уникальных элементов.
Map — коллекция пар "ключ-значение".

🚩List — упорядоченный список

List — это коллекция, в которой можно хранить дубликаты, а элементы доступны по индексу.
val numbers = listOf(1, 2, 3, 4, 5) // Immutable (нельзя изменять)
val mutableNumbers = mutableListOf(1, 2, 3) // Можно изменять

mutableNumbers.add(4) // Добавляем элемент
mutableNumbers.removeAt(1) // Удаляем элемент по индексу

println(mutableNumbers) // [1, 3, 4]


🚩Set — множество уникальных элементов

Set — это коллекция, в которой нет дубликатов.
val numbers = setOf(1, 2, 3, 3, 4, 5) // Дубликаты удаляются автоматически
println(numbers) // [1, 2, 3, 4, 5]

val mutableNumbers = mutableSetOf(1, 2, 3)
mutableNumbers.add(3) // Не добавится, потому что уже есть
mutableNumbers.add(4) // Добавится

println(mutableNumbers) // [1, 2, 3, 4]


🚩Map — коллекция пар "ключ-значение"

Map — это структура данных, в которой каждому ключу соответствует одно значение.
val userMap = mapOf(
1 to "Alice",
2 to "Bob",
3 to "Charlie"
) // Immutable

val mutableUserMap = mutableMapOf(1 to "Alice", 2 to "Bob")
mutableUserMap[3] = "Charlie" // Добавляем новый ключ-значение
mutableUserMap.remove(1) // Удаляем элемент по ключу

println(mutableUserMap) // {2=Bob, 3=Charlie}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
🤔 Без чего сервис не запустится в новых версиях Android?

Сервис не запустится без разрешения и foreground-нотификации, если он работает в фоне на Android 8.0 и выше. Также необходимо явно указать сервис в манифесте, и для долгоживущих задач использовать foregroundService, иначе система его завершит.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1🔥1
🤔 Как бороться с тем что из-за deeplink активити может открыться много раз?

Когда используется deeplink, может возникнуть проблема, что одно и то же Activity может быть открыто несколько раз в стеке задач. Это происходит, если приложение запускается из внешнего источника (например, из браузера или другого приложения), и Android создает новую задачу или новую копию Activity вместо использования уже существующей. Чтобы справиться с этим, нужно правильно настроить launchMode, интенты и флаги.

🚩Причина проблемы

При запуске приложения через deep link, система Android может:
1. Создать новый экземпляр вашего Activity (даже если оно уже существует в стеке задач).
2. Поместить новую задачу в стек задач.
Если это не контролировать, пользователь может увидеть много дубликатов одного и того же Activity, что плохо для UX и может вызвать утечку памяти.

🚩Решения

🟠Использование launchMode в манифесте
В файле AndroidManifest.xml можно настроить поведение Activity с помощью атрибута launchMode:
singleTop: Если Activity уже находится на вершине стека, система не будет создавать новый экземпляр.
singleTask: Убедитесь, что только один экземпляр Activity существует в задаче. Если Activity уже существует, система передаст интент в метод onNewIntent().
singleInstance: Подходит для случаев, когда Activity должно быть абсолютно уникальным (используется редко).
<activity
android:name=".MyActivity"
android:launchMode="singleTop" />


🟠Использование флагов в интенте
Если вы используете deep link или запускаете Activity вручную, можно добавить флаги, чтобы управлять созданием экземпляров:

   val intent = Intent(this, MyActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP
startActivity(intent)


🟠Обработка метода onNewIntent()
Если используется singleTop или singleTask, система вызывает метод onNewIntent(Intent intent) вместо создания нового экземпляра Activity. Этот метод можно переопределить для обработки новых данных из интента

   override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
// Обработка нового интента
val data = intent?.data
// Используйте данные deeplink
}


🟠Использование taskAffinity
Если требуется, чтобы разные deep link открывали одну и ту же задачу, можно настроить taskAffinity. Это нужно реже, но полезно, если нужно обрабатывать ссылки с разными контекстами.

🟠Проверка состояния Activity
Дополнительно можно вручную проверять, существует ли нужное Activity в текущем состоянии приложения, например, используя LiveData или ViewModel.

Файл AndroidManifest.xml
<activity
android:name=".MyActivity"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="https"
android:host="example.com"
android:path="/deeplink" />
</intent-filter>
</activity>


Файл MyActivity.kt
class MyActivity : AppCompatActivity() {

override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
// Обработка данных из нового интента (deeplink)
val uri = intent?.data
uri?.let {
// Например, получить параметры из ссылки
val param = it.getQueryParameter("id")
Log.d("Deeplink", "Parameter id: $param")
}
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
🤔 Что такое ProGuard?

ProGuard — это инструмент для:
- Минификации (сжатие имён классов, методов и полей),
- Удаления неиспользуемого кода,
- Обфускации (затруднение обратной декомпиляции кода).
В Android он часто используется в прод-сборках для защиты кода и уменьшения размера APK.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4👍1
🤔 Расскажи про инициализаторы в классах в Kotlin

В Kotlin инициализаторы используются для выполнения кода при создании экземпляра класса.
Первичный (primary) конструктор
Вторичные (secondary) конструкторы
Инициализационный блок (init)

🟠Первичный конструктор
Это основной способ инициализации класса в Kotlin. Он объявляется в заголовке класса.
class User(val name: String, val age: Int)


Если нужно выполнить дополнительную логику во время создания объекта, используют блок init:
class User(val name: String, val age: Int) {
init {
println("Создан пользователь: $name, возраст: $age")
}
}


🟠Вторичные конструкторы
Они объявляются с помощью constructor и нужны, если:
Нужно несколько способов создания объекта.
Надо вызвать другой конструктор (this(...)).
class User {
var name: String
var age: Int

constructor(name: String) {
this.name = name
this.age = 18 // Значение по умолчанию
}

constructor(name: String, age: Int) {
this.name = name
this.age = age
}
}


Можно создать объект так
val user1 = User("Алекс")   // возраст будет 18  
val user2 = User("Иван", 25)


Если есть первичный конструктор, вторичный должен его вызывать через this(...)
class User(val name: String, val age: Int) {
constructor(name: String) : this(name, 18)
}


🟠`init` vs вторичный конструктор
init выполняется всегда при вызове первичного конструктора.
Вторичный конструктор создаёт альтернативный способ создания объекта.
class User(val name: String, val age: Int) {
init {
println("Создан пользователь: $name, возраст: $age")
}

constructor(name: String) : this(name, 18) {
println("Вызван вторичный конструктор")
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2🤔1
🤔 Как сделать, чтобы другое приложение могло безопасно получить авторизационный токен?

– Использовать контент-провайдер с разрешениями,
– Настроить deeplink + OAuth flow,
– Использовать AccountManager,
– Хранить токен в защищённом хранилище (Keystore) и предоставлять доступ только авторизованным приложениям.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2
🤔 Изменится ли объём памяти стека/кучи,если в приложении создано несколько потоков?

Да, объём стека изменится, а вот объём кучи останется неизменным (но нагрузка на неё увеличится).

🚩Что происходит со стеком при создании нового потока?

Стек (Stack) — это область памяти для локальных переменных и вызовов функций.
- У каждого потока (Thread) есть свой отдельный стек.
- Размер стека фиксирован и устанавливается при создании потока.
- Чем больше потоков, тем больше памяти выделяется под стеки.
Если размер стека 1 МБ, и мы создаём 100 потоков, то под стеки уйдёт 100 МБ памяти.

🚩Что происходит с кучей (Heap) при создании потоков?

Куча (Heap) — это область памяти для объектов.
- Куча общая для всех потоков.
- Новый поток не создаёт отдельную кучу, он использует ту же самую.
- Но больше потоков → больше создаваемых объектов → больше нагрузка на сборщик мусора (GC).
Вывод: Объём кучи не меняется автоматически, но может быстрее заполняться.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3🔥1
🤔 В чём отличие Android 7 и 8?

Android 8 (Oreo) отличался:
- Фоновые ограничения (background limits).
- Notification channels.
- Picture-in-Picture режим.
- Autofill API.
- Улучшения производительности и безопасности.
- Новый формат APK-запаковки: AAB (Android App Bundles).


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
💊4🔥1
🤔 Зачем нужен DiffUtil?

DiffUtil — это утилита для быстрого обновления списков в RecyclerView. Она сравнивает старый и новый список и находит различия, чтобы обновлять только изменённые элементы, а не весь список.

🚩Проблема без `DiffUtil`

Обычное обновление списка без DiffUtil перерисовывает всё, даже если изменился один элемент.
adapter.notifyDataSetChanged() // Полностью обновляет список 


🟠Решение с `DiffUtil`
DiffUtil находит различия между старым и новым списком и обновляет только изменённые элементы.
class MyDiffUtilCallback(
private val oldList: List<User>,
private val newList: List<User>
) : DiffUtil.Callback() {

override fun getOldListSize() = oldList.size
override fun getNewListSize() = newList.size

override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return oldList[oldItemPosition].id == newList[newItemPosition].id
}

override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return oldList[oldItemPosition] == newList[newItemPosition] // Используем data class (авто `equals()`)
}
}


🚩Как использовать `DiffUtil` в `RecyclerView.Adapter`?

После создания DiffUtil.Callback, вызываем DiffUtil.calculateDiff() и передаём результат в adapter.
fun updateList(newList: List<User>) {
val diffCallback = MyDiffUtilCallback(userList, newList)
val diffResult = DiffUtil.calculateDiff(diffCallback)

userList = newList // Обновляем старый список
diffResult.dispatchUpdatesTo(this) // Обновляем только изменённые элементы
}


🟠`ListAdapter` – ещё проще!
Если используем ListAdapter, DiffUtil уже встроен.
class UserAdapter : ListAdapter<User, UserViewHolder>(DIFF_CALLBACK) {

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UserViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_user, parent, false)
return UserViewHolder(view)
}

override fun onBindViewHolder(holder: UserViewHolder, position: Int) {
holder.bind(getItem(position)) // `getItem()` уже работает с `ListAdapter`
}

companion object {
private val DIFF_CALLBACK = object : DiffUtil.ItemCallback<User>() {
override fun areItemsTheSame(oldItem: User, newItem: User): Boolean =
oldItem.id == newItem.id

override fun areContentsTheSame(oldItem: User, newItem: User): Boolean =
oldItem == newItem
}
}
}


Обновление списка в ListAdapter
adapter.submitList(newList) // DiffUtil работает внутри 🚀


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
🤔 На что можно заменить наследование и какие для этого есть способы?

– Композиция — включение объекта в класс,
– Интерфейсы/делегаты — определяют поведение без наследования,
– Делегирование — делегировать выполнение методов объекту.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥1
🤔 Что при создании классов в Kotlin изменились по сравнению с Java?

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

🚩Объявление классов и конструкторов

В Kotlin объявление классов и их конструкторов значительно упрощено.
В Java
public class Person {
private String name;
private int age;

public Person(String name, int age) {
this.name = name;
this.age = age;
}

public String getName() {
return name;
}

public int getAge() {
return age;
}
}


В Kotlin
class Person(val name: String, val age: Int)


🟠Статические члены
В Java для объявления статических членов используется ключевое слово static. В Kotlin вместо этого используются companion object.
В Java
public class MyClass {
public static final String CONSTANT = "constant";

public static void staticMethod() {
// Some code
}
}


В Kotlin
class MyClass {
companion object {
const val CONSTANT = "constant"

@JvmStatic
fun staticMethod() {
// Some code
}
}
}


🟠Data классы
Kotlin предоставляет специальный тип классов — data классы, которые автоматически генерируют методы equals(), hashCode(), toString(), copy(), и componentN().
В Java
public class User {
private String name;
private int age;

public User(String name, int age) {
this.name = name;
this.age = age;
}

@Override
public boolean equals(Object o) {
// Implementation
}

@Override
public int hashCode() {
// Implementation
}

@Override
public String toString() {
// Implementation
}
}


В Kotlin
data class User(val name: String, val age: Int)


🟠Свойства и методы доступа
В Kotlin свойства объявляются напрямую, и методы доступа (геттеры и сеттеры) генерируются автоматически.
В Java
public class Rectangle {
private int width;
private int height;

public int getWidth() {
return width;
}

public void setWidth(int width) {
this.width = width;
}

public int getHeight() {
return height;
}

public void setHeight(int height) {
this.height = height;
}
}


В Kotlin
class Rectangle(var width: Int, var height: Int)


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
🤔 Почему в приложении много манифестов?

При использовании библиотек и модулей, каждая библиотека может содержать собственный AndroidManifest.xml. При сборке все манифесты объединяются в итоговый файл с учетом правил мёрджа.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3
🤔 Как работает jetpackCompose?

Jetpack Compose – это декларативный UI-фреймворк от Google для создания интерфейсов в Android. Вместо традиционных XML + View в Compose используется функции-компоненты, которые описывают UI.

🟠Главные принципы работы Jetpack Compose
Декларативный подход – UI создаётся через функции, без XML.
еактивность – UI автоматически обновляется, если данные изменились.
Компонентный подход – UI состоит из маленьких, переиспользуемых функций.
Composable-функции (@Composable) – основной строительный блок Compose.

🟠Как создаётся UI в Compose?
Вместо Activity и Fragment с findViewById() используется @Composable-функции.
@Composable
fun Greeting(name: String) {
Text(text = "Привет, $name!")
}

@Composable
fun MyScreen() {
Column {
Greeting("Андрей")
Greeting("Мария")
}
}

@Preview
@Composable
fun PreviewMyScreen() {
MyScreen()
}


🟠Реактивность: автоматическое обновление UI
Jetpack Compose использует реактивный подход, где UI обновляется при изменении состояния.
@Composable
fun Counter() {
var count by remember { mutableStateOf(0) } // Реактивное состояние

Column {
Text("Счётчик: $count")
Button(onClick = { count++ }) {
Text("Увеличить")
}
}
}


🟠Основные UI-компоненты в Compose
Текст
Text(text = "Привет, мир!", fontSize = 20.sp)


Кнопка
Button(onClick = { /* действие */ }) {
Text("Нажми меня")
}


Ввод текста (TextField)
var text by remember { mutableStateOf("") }

TextField(value = text, onValueChange = { text = it })


Размещение элементов (вертикально/горизонтально)
Column {
Text("Первый элемент")
Text("Второй элемент")
}

Row {
Text("Слева")
Text("Справа")
}


🟠Взаимодействие с ViewModel
Compose работает с MVVM через ViewModel и LiveData / StateFlow.
class MyViewModel : ViewModel() {
private val _count = MutableStateFlow(0)
val count: StateFlow<Int> = _count

fun increment() {
_count.value++
}
}

@Composable
fun CounterScreen(viewModel: MyViewModel = viewModel()) {
val count by viewModel.count.collectAsState()

Column {
Text("Счётчик: $count")
Button(onClick = { viewModel.increment() }) {
Text("Добавить")
}
}
}


🟠Навигация в Jetpack Compose
Вместо Fragment используется NavController.
@Composable
fun MyApp() {
val navController = rememberNavController()
NavHost(navController, startDestination = "home") {
composable("home") { HomeScreen(navController) }
composable("details") { DetailsScreen() }
}
}


Теперь можно перейти на другой экран так
navController.navigate("details")


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
💊4👍3
🤔 Какие есть реализации List?

- ArrayList — массивная, быстрая при доступе по индексу.
- LinkedList — список на узлах, эффективен при частых вставках/удалениях.
- Vector — устаревший, синхронизированный.
- CopyOnWriteArrayList — потокобезопасный.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3👍2
🤔 Расскажи про коллекцию Map

Map – это коллекция пар ключ-значение. Каждый ключ уникален, а значения могут повторяться. В Kotlin Map не наследуется от Collection, но является частью стандартных коллекций.

🟠Виды `Map` в Kotlin
В Kotlin есть два основных типа Map:
Map (неизменяемая) – нельзя добавлять/удалять элементы после создания.
MutableMap (изменяемая) – можно добавлять, удалять и изменять элементы.

Создаётся с помощью mapOf()
val users = mapOf(1 to "Alice", 2 to "Bob", 3 to "Charlie")
println(users[1]) // Выведет: Alice


Создаётся с помощью mutableMapOf()
val users = mutableMapOf(1 to "Alice", 2 to "Bob")
users[3] = "Charlie" // Добавляем элемент
users[1] = "Alex" // Изменяем значение по ключу
users.remove(2) // Удаляем элемент
println(users) // {1=Alex, 3=Charlie}


🟠Основные операции с `Map`
map[key] – получить значение (или null, если ключа нет).
map.getValue(key) – получить значение (или исключение, если ключа нет).
map.getOrDefault(key, defaultValue) – вернуть значение или defaultValue, если ключа нет.
map.getOrElse(key) { default } – если ключа нет, выполнить лямбда-выражение.
val users = mapOf(1 to "Alice", 2 to "Bob")
println(users[1]) // Alice
println(users.getOrDefault(3, "Unknown")) // Unknown


🟠Проверка наличия ключей и значений
map.containsKey(key) – есть ли ключ?
map.containsValue(value) – есть ли значение?
println(users.containsKey(2))  // true
println(users.containsValue("Charlie")) // false


Перебор элементов
for ((key, value) in users) {
println("ID: $key, Name: $value")
}


Фильтрация Map
val filtered = users.filter { (key, value) -> key % 2 == 0 }
println(filtered) // {2=Bob}


🚩Особенности `Map` в Kotlin

🟠Порядок элементов
mapOf() – не гарантирует порядок. linkedMapOf() – сохраняет порядок добавления.
🟠Производительность
Обычный HashMap (mutableMapOf()) – O(1) для поиска по ключу. TreeMapO(log n), но поддерживает сортировку по ключам.

val sortedUsers = sortedMapOf(3 to "Charlie", 1 to "Alice", 2 to "Bob")
println(sortedUsers) // {1=Alice, 2=Bob, 3=Charlie}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
🤔 Что известно про генерации Young, Old в GC?

- Young Generation:
- Содержит новые объекты.
- Быстрое создание и удаление.
- Делится на Eden и два Survivor-пула.
- GC здесь называется Minor GC и работает быстро.
- Old Generation (Tenured):
- Хранит объекты, пережившие несколько циклов GC.
- Удаление объектов тут требует более тяжёлой и полной сборки — Major GC.
Такой подход (генерационная модель) помогает оптимизировать производительность, так как большинство объектов "умирает молодыми".


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2👍1