Добавить уникальные буквы данной строки в список

Я хочу добавить строковые буквы в список, но я хочу только добавить каждую букву один раз. Например, если строка "HELLO AM CHRISTOS WHITE", некоторые буквы появляются более одного раза, поэтому я хочу, чтобы они добавлялись только один раз.

Я думаю о двух циклах:

for (int i=0; i< str.length(); i++){
    for(int j=0; j< str.length(); j++){
        if (str.charAt(i) != str.charAt(j)) {
            myList.add(charAt(i));
        }
    }
}

Но этот код не избегает дубликатов.

Ответ 1

Было бы более эффективно использовать LinkedHashSet для определения уникальных символов. Если вы используете LinkedHashSet, порядок уникальных символов входной строки будет сохранен.

После одного цикла, который займет линейное время, вы можете добавить все уникальные символы к вашему выводу List.

Set<Character> unique = new LinkedHashSet<>();
for (int i = 0; i < str.length(); i++){
    unique.add(str.charAt(i));
}
myList.addAll(unique);

Ответ 2

Чтобы предотвратить дублирование в коллекции, вам не нужно List, вам нужен Set (например, HashSet).

Если вы хотите сохранить заказ, добавляете свои String s, используйте LinkedHashSet.

Наконец, если вы хотите, чтобы ваш Set естественно отсортировал ваш String (или чтобы отсортировать их с помощью Comparator), используйте TreeSet.

Пример

String foo = "ghghababcdef";
Set<String> hash = new HashSet<>();
Set<String> linked = new LinkedHashSet<>();
Set<String> tree = new TreeSet<>();
// iterating characters
for (char c: foo.toCharArray()) {
    // adding String representation of character to each set
    hash.add(Character.toString(c));
    linked.add(Character.toString(c));
    tree.add(Character.toString(c));
}
// printing...
System.out.println(hash);
System.out.println(linked);
System.out.println(tree);

Выход

[a, b, c, d, e, f, g, h] // this may vary
[g, h, a, b, c, d, e, f] // keeps insertion order
[a, b, c, d, e, f, g, h] // sorted lexicographically by default

Ответ 3

в качестве альтернативы ответе Set, если вы хотите придерживаться решения List. Вам нужно всего лишь выполнить цикл и использовать метод List.contains(Object) и проверить, присутствует ли текущий char в вашем List.

String str = "HELLO AM CHRISTOS WHITE";
List<Character> myList = new ArrayList<>();
for(int i=0; i< str.length(); i++){
    if (!myList.contains(str.charAt(i))) {
        myList.add(str.charAt(i));
    }
}
for(char c : myList) {
    System.out.println(c);
}

Выход

HELO AMCRISTW

Ответ 4

j не назначается. Я предполагаю, что он инициализирован 0, поэтому исключение не существует

Если вы измените второй цикл на for(int j=0; j< str.length(); j++), он все равно не будет работать, он не будет печатать буквы, которые дублируются в строке.

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

Ответ 5

К сожалению, в Java 8 нет потока символов, но здесь есть способ Java 8:

str.chars().distinct().mapToObj(c -> (char) c).collect(Collectors.toList());

Он может быть менее эффективным, но это читаемый один лайнер, и он показывает мощь потоков.