Как написать Java-программу для печати только повторяющегося символа в строке? - PullRequest
0 голосов
/ 24 сентября 2019

Я хочу напечатать повторяющиеся символы из строки, используя только наборы (Set).

Я написал код, но он покажет правильный результат, если String «ashish», но завершится неудачей, если String «ashish».java "из-за появления символа 'a' три раза.

public class DuplicateStringMethod {
    public static void duplicateString(String str) {
        char[] cArray = str.toCharArray();
        Set<Character> set = new HashSet<Character>();

        for(char c:cArray) {
            if(set.add(c)==false) {
                System.out.println(c);
            }
        }
    }

    public static void main(String[] args) {
        duplicateString("Java ashishj ");
    }
}

Будет напечатано a a s h.Но я хочу a s h, используя только Set интерфейс.

Ответы [ 6 ]

1 голос
/ 24 сентября 2019

Попробуйте:

public static void duplicateString(String str) {
    Set<Character> firstTime = new HashSet<Character>();
    Set<Character> reported = new HashSet<Character>();

    char[] cArray = str.toCharArray();
    for(char c:cArray) {
        if (!firstTime.contains(c)) {
          firstTime.add(c);
          continue;
        }
        if (reported.contains(c)) { continue; }
        reported.add(c);
        System.out.println(c);
    }
}

По предложению Хольгера я провел несколько тестов:

  • add: 52443260ns для 10000000 операций
  • содержит:28209745 нс для 10000000 операций

Поэтому приведенный выше код, хотя и не короче, самый быстрый.

0 голосов
/ 25 сентября 2019

Мне не совсем понятно, что требуется для "использования только интерфейса Set", но я предполагаю, что это означает, что повторяющиеся символы должны быть возвращены в Set.Есть несколько способов сделать это.Первый - это простой цикл над символами входной строки.Он использует функцию Set.add, которая возвращает true, если набор был изменен, и false, если это не так;это означает, что операция add, которая возвращает false, является дубликатом.

static Set<Character> dups0(String input) {
    Set<Character> dups = new HashSet<>();
    Set<Character> seen = new HashSet<>();
    for (char ch : input.toCharArray()) {
        if (! seen.add(ch)) {
            dups.add(ch);
        }
    }
    return dups;
}

Существует потоковый способ сделать это, что по сути то же самое, что выражено в виде потока:

static Set<Character> dups1(String input) {
     Set<Character> seen = new HashSet<>();
     return input.chars()
                 .mapToObj(ch -> (char)ch)
                 .filter(ch -> !seen.add(ch))
                 .collect(toSet());
}

Некоторые люди могут посчитать это неприятным, поскольку его операция фильтра вызывает побочные эффекты.Кроме того, если это выполняется параллельно, результатом должно быть что-то вроде ConcurrentHashMap.newKeySet.

Альтернативой является генерация таблицы частот символов и удаление всех записей, которые встречаются только один раз:

static Set<Character> dups2(String input) {
     Map<Character, Long> map = input.chars()
                                     .mapToObj(i -> (char)i)
                                     .collect(groupingBy(ch -> ch, counting()));
     map.values().removeIf(v -> v == 1);
     return map.keySet();
}

Обратите внимание, что при этом используется массовая операция сбора в представлении сбора значений карты.Если вам не нравится мутация, есть способ сделать это с помощью чистых потоков:

static Set<Character> dups3(String input) {
    Map<Character, Long> map = input.chars()
                                    .mapToObj(i -> (char)i)
                                    .collect(groupingBy(ch -> ch, counting()));
    return map.entrySet().stream()
              .filter(entry -> entry.getValue() > 1)
              .map(Map.Entry::getKey)
              .collect(toSet());
}
0 голосов
/ 24 сентября 2019

Вы можете использовать String.split () здесь.Этот метод разбивает строку на массив строк на основе предоставленного регулярного выражения.Мы будем использовать «», потому что мы хотим разбить строку после каждого символа, а затем ввести результаты в поток.

public static void duplicateString( String str ) {

    // collect all characters in a map, whose String value is the character and whose key value is the count of occurrences in the string
    Map<String,Long> charCountMap = Arrays.stream( str.split( "" ) )
            .filter( charInString -> !charInString.equals( " " ) ) // don't want spaces
            .collect( Collectors.groupingBy( Function.identity(), Collectors.counting() ) );

    charCountMap.entrySet()
            .stream()
            .filter( entrySet -> entrySet.getValue() > 1 ) // filter out occurrences that are one or less
            .forEach( entrySet -> System.out.println( String.format( "Char %s appeared %d times", entrySet.getKey(), entrySet.getValue() ) ) );
}
0 голосов
/ 24 сентября 2019
public static void main(String[] args) {
        String s = "Javaashishj";
        char[] cArray = s.toCharArray();
        Set<Character> set = new HashSet<Character>();
        for (char c : cArray) {
            if (!set.contains(c)) {
                set.add(c);
                System.out.println(c);
            }
        }
    }
0 голосов
/ 24 сентября 2019

Все, что вам нужно сделать, это использовать метод add() класса Set, чтобы сообщить вам, является ли вставляемая (добавляемая) вещь уже частью набора.Когда функция возвращает false, это означает, что текущая добавляемая вещь является дубликатом. Затем добавьте это к Set дубликатов.Таким образом, элементы, дублированные более одного раза, будут отображаться только один раз в новом наборе .Наконец, чтобы сохранить порядок, вы можете использовать LinkedHashSet для хранения дубликатов.

public class TestDups {

    public static void main (String[] args) {
        String str = "Java ashishj ";
        Set<Byte> myset = new TreeSet<>();
        Set<Character> dups = new LinkedHashSet<>();
        for (byte c: str.getBytes() ) {
            if (!myset.add(c)) {
                dups.add((char)c);
            }
        }

        dups.stream().forEach(System.out::print);
    }
}

Вывод кода выше - "пепел".Обратите внимание на пробел в конце, так как исходная строка содержит два пробела (между словами и в конце).

0 голосов
/ 24 сентября 2019

Проверить эту программу

public static void duplicateString(String str) {

        char[] cArray = str.replaceAll("\\s+", "").toCharArray();

        Set<Character> set = new HashSet<Character>();
        Set<Character> alreadyExistingSet = new HashSet<Character>();

        for (char c : cArray) {
            if (set.add(c) == false && alreadyExistingSet.add(c) == true) {
                System.out.print(c);
            }
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...