Uma das desvantagens das listas é o custo linear das operações de pesquisa e remoção. A utilização de conjuntos não tem o mesmo custo nestas operações, e poderá ser uma alternativa adequada.
Um conjunto é uma coleção de elementos sem duplicados. Por comparação a uma lista, a inserção de um elemento repetido não terá efeito. A principal vantagem do conjunto é a eficiência da operação de verificação de existência de elemento (contains), pois a concretização baseia-se numa tabela de dispersão (custo constante, por comparação a custo linear numa lista).
Normalmente, num conjunto a ordem pela qual os elementos são inseridos não dá garantias sobre a ordem de interação. Por conseguinte, um conjunto não é adequado para manter informação de algo onde a relação de ordem dos elementos é relevante. Porém, se utilizarmos a implementação por omissão em Kotlin, o conjunto mantém a ordem de inserção, por forma a que uma iteração pelos elementos corresponde à ordem pela qual foram adicionados.
Tal como nas listas, temos uma abstração para leitura de conjuntos e outra para alteração.
Conjuntos para leitura (read-only)
Nas operações, temos algumas idênticas à lista, mas note-se que não existem operações com indexação (pois não existe tal concepção em conjuntos). Na verdade, o Kotlin fornece algumas funções adicionais (via extensões) que manipulam índices em conjuntos. Porém, essas operações são desaconselhadas em termos de desempenho, pois têm um custo linear.
Operação | Descrição | Custo | Exemplo | Resultado |
---|---|---|---|---|
size | Número de elementos | Constante | stringSet.size | 3 |
isEmpty | Conjunto é vazio? | Constante | stringSet.isEmpty | false |
contains(*) | Conjunto contém elemento? | Constante | list.contains(“quatro”) | false |
Conjuntos mutáveis
Também no caso dos conjuntos mutáveis, algumas operações são equivalentes às listas mutáveis, mas não temos operações com base em índices. A principal diferença é que invocar add com um elemento que já existe não terá efeito no conjunto. Relativamente a desempenho, de realçar que o custo de remove é constante.
Operação | Descrição | Custo | Exemplo | Resultado |
---|---|---|---|---|
add(*) | Adiciona elemento | Constante | stringSet.add(“quatro”) | [“um”, “dois”, “tres”, “quatro”] |
remove(*) | Remove elemento | Constante | stringSet.remove(“dois”) | [“um”, “tres”] |
clear() | Remove todos os elementos | Constante | stringSet.clear() | [] |
Exemplo: Função para obter os elementos de uma lista sem duplicados (num conjunto). O custo temporal é linear: a lista é iterada na totalidade, mas a inserção no conjunto tem um custo constante.