Возник вопрос: Как удалить одинаковые буквы из строки? Есть вот это:
for(int i = 0; i < word[0].length(); i++) {
for(int j = 1; j < word[0].length(); j++) {
if(word[0].charAt(i) == word[0].charAt(j)) {
word[0] = word[0].replace((word[0].charAt(i)), "");
word[0] = word[0].replace((word[0].charAt(j)), "");
}
}
}
Насколько я понимаю проблема в этой строчке
word[0] = word[0].replace((word[0].charAt(i)), "");
Видимо я пытаюсь заменить char на string, поэтому и не работает. Пожалуйста, подскажите как мне реализовать эту функцию.
Пример работы, должно быть так: на входе - Java на выходе - Jv То есть должны удаляться все символы, встречающиеся более 1 раза
String str = "Java 8 RulezZz";
Map<Integer, Long> frequencies = str.toLowerCase()
.codePoints()
.boxed()
.collect(Collectors.groupingBy(
Function.identity(), Collectors.counting()));
String duplicates = frequencies.entrySet()
.stream()
.filter(e -> e.getValue() > 1)
.map(Map.Entry::getKey)
.map(Character::toChars)
.map(String::valueOf)
.filter(i -> !i.equals(" "))
.collect(Collectors.joining());
System.out.println(str.replaceAll("(?i)[" + duplicates + "]", ""));
Код в основном использует появившееся в Java 8 механизмы функционального программирования - Stream API, лямбды и ссылки на методы. Google поможет найти огромное количество вводных статей в эту область. Если хочется ознакомиться с вопросом подробнее, могу посоветовать учебник Уорбэртона "Лямбда-выражения в Java 8" или "Java SE 8 Базовый курс" Хорстманна. Попробую разобрать пример построчно:
str.codePoints()
- вызов метода codePoints() возвращает поток элементов типа int
. Каждый элемент представляет код символа в оригинальной строке.
Вызов boxed()
упаковывает каждый int в потоке в Integer.
Вызов collect()
- терминальная операция преобразующая поток во что-либо. В данном случаем мы передаём параметром предопределённый коллектор groupBy
, использующийся для группировки элементов.
Первым параметром коллектора мы передаём результат вызова статического метода Function.identity()
, который возвращает лямбда-выражение, в свою очередь, возвращающее без изменений всё, что ему передадут. Можно было вместо Function.identity()
написать i -> i
.
Вторым параметром коллектора мы передаём результат вызова статического метода Collectors.counting()
, который возвращает коллектор подсчитывающий количество элементов в потоке.
В результате манипуляций с этим потоком мы получаем в переменную frequencies
отображение (Map), содержащий в ключах коды символов, а в значениях количество раз, который этот код встретился в потоке:
{32=2, 97=2, 82=1, 101=1, 117=1, 118=1, 56=1, 90=1, 122=2, 74=1, 108=1}
Вызов frequencies.entrySet()
возвращает множество элементов отображения, которое мы тут же преобразуем в новый поток вызовом stream()
.
В следующей строке - filter(e -> e.getValue() > 1)
мы отфильтровываем элементы значения которых равны единицы, то есть встретились в первом потоке только один раз.
Вызов map(Map.Entry::getKey)
отбрасывает значения элементов, оставляя в потоке только ключи, так как значения нам больше не нужны, мы уже использовали их для фильтрации на предыдущем шаге.
Вызов map(Character::toChars)
преобразует коды символов в сами символы.
Вызов map(String::valueOf)
преобразует символы в строки.
Вызов filter(i -> !i.equals(" "))
отфильтровывает пробелы. Мы же не хотим, чтобы в результате удаления дублирующихся пробелов в нашей итоговой строке все слова слиплись.
И, как и прошлый, этот поток заканчивается коллектором - .collect(Collectors.joining())
, но на этот раз объединяющим отдельные строки потока в одну результирующую.
В результате манипуляций со вторым потоком мы получаем строку, содержащую все символы, которые встретились в оригинальной строке более одного раза, исключая пробелы.
Вызовом метода String.replaceAll() мы разом удаляем из str
все символы duplicates
. Первым параметром метод получает регулярное выражение. Его первая часть - (?i)
означает, что метод должен игнорировать регистр символов. Вторая часть, образующаяся в результате конкатенации - [az]
представляет набор символов, которые надо заменить. Вторым параметром метода передаётся строка, на которую эти символы необходимо заменить. Так как нам надо их удалить, то заменяем мы их на пустую строку.
Или можно в императивном стиле:
Map<Character, Integer> chars = new HashMap<>();
StringBuilder sb = new StringBuilder();
for (char c : str.toLowerCase().toCharArray()) {
if (c != ' ')
chars.merge(c, 1, Integer::sum);
}
sb.append("(?i)[");
for (Map.Entry<Character, Integer> entry : chars.entrySet()) {
if (entry.getValue() > 1)
sb.append(entry.getKey());
}
sb.append("]");
System.out.println(str.replaceAll(sb.toString(), ""));
Set<Character> chars = new HashSet();
for(int i = 0; i<string.length(); i++){
chars.add(string.charAt(i));
}
ideone
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Навеяно статьёй о различиях DTO, POCO и Value Object на Хабрахабре: DTO vs POCO vs Value Object, а также вопросом POCO vs DTO
Например, чтобы обработать нажатие на Button необходимо воспользоваться методом setOnClickListener передав оному OnClickListener (слушатель)И такой Listener много...
Можно ли создать exe файл в JAVA? И можно ли будет его запрограммировать?