Как найти все буквы в строке java

Looking back at the original question, we need to find some given keywords in a given sentence, count the number of occurrences and know something about where. I don’t quite understand what “where” means (is it an index in the sentence?), so I’ll pass that one… I’m still learning java, one step at a time, so I’ll see to that one in due time 🙂

It must be noticed that common sentences (as the one in the original question) can have repeated keywords, therefore the search cannot just ask if a given keyword “exists or not” and count it as 1 if it does exist. There can be more then one of the same. For example:

// Base sentence (added punctuation, to make it more interesting):
String sentence = "Say that 123 of us will come by and meet you, "
                + "say, at the woods of 123woods.";

// Split it (punctuation taken in consideration, as well):
java.util.List<String> strings = 
                       java.util.Arrays.asList(sentence.split(" |,|\."));

// My keywords:
java.util.ArrayList<String> keywords = new java.util.ArrayList<>();
keywords.add("123woods");
keywords.add("come");
keywords.add("you");
keywords.add("say");

By looking at it, the expected result would be 5 for “Say” + “come” + “you” + “say” + “123woods”, counting “say” twice if we go lowercase. If we don’t, then the count should be 4, “Say” being excluded and “say” included. Fine. My suggestion is:

// Set... ready...?
int counter = 0;

// Go!
for(String s : strings)
{
    // Asking if the sentence exists in the keywords, not the other
    // around, to find repeated keywords in the sentence.
    Boolean found = keywords.contains(s.toLowerCase());
    if(found)
    {
        counter ++;
        System.out.println("Found: " + s);
    }
}

// Statistics:
if (counter > 0)
{
    System.out.println("In sentence: " + sentence + "n"
                     + "Count: " + counter);
}

And the results are:

Found: Say
Found: come
Found: you
Found: say
Found: 123woods
In sentence: Say that 123 of us will come by and meet you, say, at the woods of 123woods.
Count: 5

I am trying to check if a string contains all the letters of the alphabet. I created an ArrayList which contains the whole alphabet. I converted the string to char array and I’m iterating through the character array, and for every character present in the ArrayList I’m removing an element from it. And in the end, I’m trying to check if the Arraylist is empty to see if all elements have been removed. That would indicate the string contains all the letters of the alphabet.

Unfortunately, the code is throwing IndexOutOfBoundsException error inside the if condition where I’m removing elements from the arraylist

List<Character> alphabets = new ArrayList<Character>();

alphabets.add('a');
alphabets.add('b');
alphabets.add('c');
alphabets.add('d');
alphabets.add('e');
alphabets.add('f');
alphabets.add('g');
alphabets.add('h');
alphabets.add('i');
alphabets.add('j');
alphabets.add('k');
alphabets.add('l');
alphabets.add('m');
alphabets.add('n');
alphabets.add('o');
alphabets.add('p');
alphabets.add('q');
alphabets.add('r');
alphabets.add('s');
alphabets.add('t');
alphabets.add('u');
alphabets.add('v');
alphabets.add('w');
alphabets.add('x');
alphabets.add('y');
alphabets.add('z');

// This is the string- I've just put a random example
String str = "a dog is running crazily on the ground who doesn't care about the world";

//Remove all the spaces
str = str.replace(" ", "");

// Convert the string to character array
char[] strChar = str.toCharArray();

for (int i = 0; i < strChar.length; i++) {

    char inp = strChar[i];

    if (alphabets.contains(inp)) {
        alphabets.remove(inp);
    }
}

if (alphabets.isEmpty())
    System.out.println("String contains all alphabets");
else
    System.out.println("String DOESN'T contains all alphabets");

Szymon's user avatar

asked Sep 1, 2016 at 6:03

Siddharth's user avatar

8

All these solutions seem to do a lot of work for a relatively simple check, especially given Java 8’s stream API:

/* Your lowercase string */.chars()
    .filter(i -> i >= 'a' && i <= 'z')
    .distinct().count() == 26;

Edit: For speed

If you want to end the string iteration as soon as the entire alphabet is found while still using streams, then you can keep track with a HashSet internally:

Set<Integer> chars = new HashSet<>();
String s = /* Your lowercase string */;
s.length() > 25 && s.chars()
    .filter(i -> i >= 'a' && i <= 'z') //only alphabet
    .filter(chars::add)                //add to our tracking set if we reach this point
    .filter(i -> chars.size() == 26)   //filter the 26th letter found
    .findAny().isPresent();            //if the 26th is found, return

This way, the stream will cease as soon as the Set is filled with the 26 required characters.

There are some (even still) more efficient solutions in terms of performance below, but as a personal note I will say to not bog yourself in premature optimization too much, where you could have readability and less effort in writing the actual code.

answered Sep 1, 2016 at 6:21

Rogue's user avatar

RogueRogue

11k5 gold badges45 silver badges71 bronze badges

9

List.remove removes by index. Since a char can be cast to an int you are effectively removing index values that do not exist, ie char ‘a’ is equal to int 97. As you can see your list does not have 97 entries.

You can do alphabet.remove(alphabets.indexOf(inp));

As pointed out by @Scary Wombat(https://stackoverflow.com/a/39263836/1226744) and @Kevin Esche (https://stackoverflow.com/a/39263917/1226744), there are better alternative to your algorithm

Community's user avatar

answered Sep 1, 2016 at 6:09

Leon's user avatar

LeonLeon

11.9k5 gold badges35 silver badges59 bronze badges

2

O(n) solution

static Set<Integer> alphabet = new HashSet<>(26);

public static void main(String[] args) {

    int cnt = 0;

    String str = "a dog is running crazily on the ground who doesn't care about the world";

    for (char c : str.toCharArray()) {
        int n = c - 'a';
        if (n >= 0 && n < 26) {
            if (alphabet.add(n)) {
                cnt += 1;
                if (cnt == 26) {
                    System.out.println("found all letters");
                    break;
                }
            }
        }
    }
}

answered Sep 1, 2016 at 7:01

hahn's user avatar

hahnhahn

3,57820 silver badges31 bronze badges

2

Adding to @Leon answer, creating a List and removing from it seems quite unnecessary. You could simply loop over 'a' - 'z' and do a check with each char. Additionally you are looping over the whole String to find out, if each letter is present. But the better version would be to loop over each letter itself. This can potentionally safe you a few iterations.

In the end a simple example could look like this:

// This is the string- I've just put a random example
String str = "a dog is running crazily on the ground who doesn't care about the world";
str = str.toLowerCase();

boolean success = true;
for(char c = 'a';c <= 'z'; ++c) {
    if(!str.contains(String.valueOf(c))) {
        success = false;
        break;
    }
}

if (success)
    System.out.println("String contains all alphabets");
else
    System.out.println("String DOESN'T contains all alphabets");

answered Sep 1, 2016 at 6:14

SomeJavaGuy's user avatar

SomeJavaGuySomeJavaGuy

7,2972 gold badges21 silver badges33 bronze badges

1

Regex is your friend. No need to use a List here.

public static void main(String[] args) {
    String s = "a dog is running crazily on the ground who doesn't care about the world";
    s = s.replaceAll("[^a-zA-Z]", ""); // replace everything that is not between A-Za-z 
    s = s.toLowerCase();
    s = s.replaceAll("(.)(?=.*\1)", ""); // replace duplicate characters.
    System.out.println(s);
    System.out.println(s.length()); // 18 : So, Nope

    s = "a dog is running crazily on the ground who doesn't care about the world qwertyuioplkjhgfdsazxcvbnm";
    s = s.replaceAll("[^a-zA-Z]", "");
    s = s.toLowerCase();        
    s = s.replaceAll("(.)(?=.*\1)", "");
    System.out.println(s);
    System.out.println(s.length()); //26 (check last part added to String)  So, Yes

}

answered Sep 1, 2016 at 6:14

TheLostMind's user avatar

TheLostMindTheLostMind

35.9k12 gold badges68 silver badges104 bronze badges

5

Another answer has already pointed out the reason for exception. You have misused List.remove(), as it implicitly convert char to int which it called the List.remove(int) which remove by index.

The way to solve is actually easy. You can make it call the List.remove(Object) by

alphabets.remove((Character) inp);

Some other improvements:

  1. You should use Set instead of List in this case.
  2. You can even use a boolean[26] to keep track of whether an alphabet has appeared
  3. You do not need to convert your string to char array. Simply do a str.charAt(index) will give you the character at certain position.

answered Sep 1, 2016 at 6:13

Adrian Shum's user avatar

Adrian ShumAdrian Shum

38.4k10 gold badges80 silver badges130 bronze badges

One integer variable is enough to store this information. You can do it like this

public static boolean check(String input) {
  int result = 0;    
  input = input.toLowerCase();
  for (int i = 0; i < input.length(); i++) {
    char c = input.charAt(i);
    if (c >= 'a' && c <= 'z') {
      result |= 1 << (input.charAt(i) - 'a');
    }
  }
  return result == 0x3ffffff;
}

Each bit corresponds to a letter in English alphabet. So if your string contains all letters the result will be of form 00000011111111111111111111111111

answered Sep 1, 2016 at 10:08

cliffroot's user avatar

cliffrootcliffroot

1,83917 silver badges27 bronze badges

1

How about creating

List<String> alphabets = new ArrayList <String> ();

and add values as strings

then

for (String val : alphabets) {   // if str is long this will be more effecient
     if (str.contains (val) == false) {
        System.out.println ("FAIL");
        break;
     }
}

answered Sep 1, 2016 at 6:09

Scary Wombat's user avatar

Scary WombatScary Wombat

44.5k5 gold badges35 silver badges64 bronze badges

You can get rid of the exception, by changing this line in your code

char inp = strChar[i];

to

Character inp = strChar[i];

Refer https://docs.oracle.com/javase/7/docs/api/java/util/List.html#remove(java.lang.Object)

List.remove('char') is treated as List.remove('int'), which is why you are getting indexOutOfBoundsException, because it is checking the ASCII value of ‘a’ which is 97. Converting variable ‘inp’ to Character would call List.remove('Object') api.

Anoop LL's user avatar

Anoop LL

1,5382 gold badges21 silver badges32 bronze badges

answered Sep 1, 2016 at 6:46

Arathi Senan's user avatar

0

And if you like Java 8 streams like me:

final List<String> alphabets = new ArrayList<>();

And after filling alphabets with a-z:

final String str = "a dog is running crazily on the ground who doesn't care about the world";
final String strAsLowercaseAndWithoutOtherChars = str.toLowerCase()
                                                     .replaceAll("[^a-z]", "");

final boolean anyCharNotFound = alphabets.parallelStream()
       .anyMatch(t -> !strAsLowercaseAndWithoutOtherChars.contains(t));

if (anyCharNotFound) {
    System.out.println("String DOESN'T contains all alphabets");
} else {
    System.out.println("String contains all alphabets");
}

This converts the string to lower case (skip if you really are only looking for the small letters), removes all characters from the string which are not small letters and then checks for all members of your alphabets if they are contained in the string by using a parallel stream.

answered Sep 1, 2016 at 6:27

Florian Link's user avatar

Here’s another naive solution that uses String.split("") to split every character into a String[] array, then Arrays.asList() to convert that to a List<String>. You can then call yourStringAsList.containsAll(alphabet) to determine whether your String contains the alphabet:

String yourString = "the quick brown fox jumps over the lazy dog";
        
List<String> alphabet = Arrays.asList("abcdefghijklmnopqrstuvwxyz".split(""));
List<String> yourStringAsList = Arrays.asList(yourString.split(""));
        
boolean containsAllLetters = yourStringAsList.containsAll(alphabet);
        
System.out.println(containsAllLetters);

This approach might not be the fastest, but I think the code is a littler easier to understand than the solutions proposing loops and streams and whatnot.

answered Sep 1, 2016 at 16:31

Kevin Workman's user avatar

Kevin WorkmanKevin Workman

41.3k9 gold badges67 silver badges105 bronze badges

Just do something like

sentence.split().uniq().sort() == range('a', 'z')

Laurel's user avatar

Laurel

5,93314 gold badges30 silver badges57 bronze badges

answered Sep 1, 2016 at 16:22

lblzsd's user avatar

1

For Java 8, it could be written like:

boolean check(final String input) {
    final String lower = input.toLowerCase();
    return IntStream.range('a', 'z'+1).allMatch(a -> lower.indexOf(a) >= 0);
}

Laurel's user avatar

Laurel

5,93314 gold badges30 silver badges57 bronze badges

answered Sep 1, 2016 at 15:13

j2ko's user avatar

j2koj2ko

2,4791 gold badge16 silver badges29 bronze badges

Convert the string to lower case or capitals. Then loop thru the equivalent ascii decimal values for A-Z or a-z and return false if not found in character array. You will have to cast the int to char.

answered Sep 1, 2016 at 6:17

Olga's user avatar

OlgaOlga

313 bronze badges

I’ve thought about playing with the ASCII codes of the characters.

String toCheck = yourString.toLowerCase();
int[] arr = new int[26];
for(int i = 0; i < toCheck.length(); i++) {
    int c = ((int) toCheck.charAt(i)) - 97;
    if(c >= 0 && c < 26) 
        arr[c] = arr[c] + 1;
}

After running the loop you eventually get an array of counters, each representing a letter of alphabet (index) and it’s occurrence in the string.

boolean containsAlph = true;
for(int i = 0; i < 26; i++)
    if(arr[i] == 0) {
        containsAlph = false;
        break;
    }

Laurel's user avatar

Laurel

5,93314 gold badges30 silver badges57 bronze badges

answered Sep 1, 2016 at 6:19

Chernogorskiy Fedor's user avatar

1

Character inp = strChar[i]; 

Use this instead of char, List remove method have 2 overloaded methods , one with object and one with int .If you pass char its been treated as the int one.

answered Sep 1, 2016 at 6:14

Rohit's user avatar

RohitRohit

896 bronze badges

Теги: java, string, символ, поиск, строка, метод, буква, знак, contains

В этой статье мы рассмотрим, как выполнять поиск букв и других символов в строке Java, а также как проверять, находится ли нужный символ, буква или слово в строке, начиная с указанного индекса.

JavaPro_970x90-20219-3b63e7.png

Строкой в Java называют упорядоченную последовательность символов. Как правило строка в Java — это один из основных носителей текстовой информации.

Для работы со строками в Java применяют классы String, StringBuilder и StringBuffer. Класс String включает методы, возвращающие позицию символа либо подстроки в строке:
— indexOf() — для поиска с начала строки;
— lastIndexOf() — для выполнения поиска с конца строки.

Таким образом, если метод indexOf() найдёт заданную букву, символ либо строку, он вернёт индекс, то есть порядковый номер. Если не найдёт, будет возвращено -1. Также он позволяет искать символ или букву, начиная с указанного индекса.

Кроме того, стоит добавить, что класс String включает в себя ещё и метод contains, возвращающий true, когда в строке содержится заданная последовательность символов. Этот метод рекомендуется использовать лишь тогда, когда вам просто нужно узнать о существовании подстроки в строке, при этом позиция не имеет значения.

Метод indexOf()

Библиотека метода:


Синтаксис следующий:

public int indexOf(char ch)
public int indexOf(char ch, int fromIndex)

либо

public int indexOf(String s)
public int indexOf(String s, int fromIndex)

Соответственно, вызвать метод можно тоже несколькими способами:

int index = str1.indexOf(myChar);
int index = str1.indexOf(myChar, start);

или:

int index = str1.indexOf(myString);
int index = str1.indexOf(myString, start);

Представьте, что нам нужно отыскать в строке индекс первого вхождения требуемого символа/буквы, а также нужного слова. Как уже было сказано выше, метод indexOf() вернёт нам индекс первого вхождения, а в случае неудачи — вернёт -1.

JavaSpec_970x90-20219-e8e90f.png

Посмотрите на следующий код:

public class Main {
   public static void main(String[] args) {
      String str = "Otus — онлайн-образование";

      int indexM = str.indexOf("з"); // Ищем символ в строке
      int indexJava = str.indexOf("онлайн"); // Ищем слово в строке

      if(indexM == - 1) {
         System.out.println("Символ "з" не найден.");
      } else {
         System.out.println("Символ "з" найден, его индекс: " + indexM);
      }

      if(indexJava == - 1) {
         System.out.println("Слово "онлайн" не найдено.");
      } else {
         System.out.println("Слово "онлайн" найдено, его индекс: " + indexJava);
      }
   }
}

Результат получим следующий:

Символ "з" найден, его индекс: 18
Слово "онлайн" найдено, его индекс: 7

Метод contains

Бывают ситуации, когда нам необходимо проверить, содержит ли наша строка конкретный символ/букву либо слово. Нижеследующий Java-код продемонстрирует и этот пример:

public class Main {
   public static void main(String[] args) {
      String str = "Otus — онлайн-образование";
      System.out.println("Слово "Otus" есть в строке str? Ответ: " + str.contains("Otus"));
      System.out.println("Символ "z" присутствует в строке str? Ответ: " + str.contains("z"));
   }
}

В этом случае результат будет следующим:

Слово "Otus" есть в строке str? Ответ: true
Символ "z" присутствует в строке str? Ответ: false

Как видите, выполнять поиск букв и других символов в строке Java совсем несложно, и наши элементарные примеры убедительно это подтверждают. Если же вы хотите получить более продвинутые навыки по Java-разработке, добро пожаловать на наш курс:

JavaPro_970x550-20219-8420e5.png

Описание проблемы

Как найти символ или слово в строке?

Решение 1: когда нужно найти индекс первого вхождения

Следующий пример показывает как найти символ или слово в строке в Java с помощью метода indexOf(). Метод вернет индекс первого вхождения, если символ или слово не будет найдено, то метод вернет -1.

public class Example {
   public static void main(String[] args) {
      String str = "Привет, java-программист!";
      
      int indexM = str.indexOf("м"); // Нахождение символа в строке
      int indexJava = str.indexOf("java"); // Нахождение слова в строке
      
      if(indexM == - 1) {
         System.out.println("Символ "м" не найден.");
      } else {
         System.out.println("Символ "м" найден в индексе " + indexM);
      }
      
      if(indexJava == - 1) {
         System.out.println("Слово "java" не найдено.");
      } else {
         System.out.println("Слово "java" найдено в индексе " + indexJava);
      }
   }
}

Результат

Получим следующий результат:

Символ "м" найден в индексе 19
Слово "java" найдено в индексе 8

Решение 2: когда нужно узнать есть ли в строке данный символ или слово

Ниже продемонстрирован пример, который позволяет в Java узнать присутствует ли данный символ или слово в строке.

public class Example {
   public static void main(String[] args) {
      String str = "Привет, java-программист!";
      System.out.println("Слово "программист" есть в строке str? Ответ: " + str.contains("программист"));
      System.out.println("Символ "б" присутствует в строке str? Ответ: " + str.contains("б"));
   }
}

Результат

Получим следующий результат:

Слово "программист" есть в строке str? Ответ: true
Символ "б" присутствует в строке str? Ответ: false

Проверьте, содержит ли строка все буквы алфавита

  • Java
    Algorithms

Проверьте, содержит ли строка все буквы алфавита

1. обзор

В этом руководстве мы увидим, как проверить, содержит ли строка все буквы алфавита или нет.

Вот быстрый пример: «Farmer jack realized that big yellow quilts were expensive.», который действительно содержит все буквы алфавита.

Мы обсудим три подхода.

Сначала мы смоделируем алгоритм, используя императивный подход. Затем будем использовать регулярные выражения. И, наконец, мы воспользуемся преимуществами более декларативного подхода с использованием Java 8.

Кроме того, мы обсудим сложность принятых подходов.

2. Императивный алгоритм

Давайте реализуем императивный алгоритм. Для этого сначала мы создадим логический массив посещенных. Затем мы пройдемся по входной строке посимвольно и пометим символ как посещенный.

Обратите внимание, чтоUppercase иLowercase считаются одинаковыми. Таким образом, индекс 0 представляет как A, так и a, аналогично, индекс 25 представляет как Z, так и z.

Наконец, мы проверим, все ли символы в посещенном массиве имеют значение true:

public class EnglishAlphabetLetters {

    public static boolean checkStringForAllTheLetters(String input) {
        int index = 0;
        boolean[] visited = new boolean[26];

        for (int id = 0; id < input.length(); id++) {
            if ('a' <= input.charAt(id) && input.charAt(id) <= 'z') {
                index = input.charAt(id) - 'a';
            } else if ('A' <= input.charAt(id) && input.charAt(id) <= 'Z') {
                index = input.charAt(id) - 'A';
            }
            visited[index] = true;
        }

        for (int id = 0; id < 26; id++) {
            if (!visited[id]) {
                return false;
            }
        }
        return true;
    }
}

Сложность этой программы составляет O (n), гдеn – длина строки.

Обратите внимание, что есть много способов оптимизировать алгоритм, например, удаление букв из набора и прерывание, как толькоSet станет пустым. Однако для целей упражнения этот алгоритм достаточно хорош.

3. Использование регулярного выражения

Используя регулярные выражения, мы можем легко получить те же результаты с помощью нескольких строк кода:

public static boolean checkStringForAllLetterUsingRegex(String input) {
    return input.toLowerCase()
      .replaceAll("[^a-z]", "")
      .replaceAll("(.)(?=.*\1)", "")
      .length() == 26;
}

Здесь мы сначала удаляем все символы, кроме букв алфавита, изinput. Затем мы удаляем дубликаты символов. Наконец, мы считаем буквы и следим за тем, чтобы у нас их было все 26.

Хотя Big-O-Complexity этого подхода менее производительный, он также имеет тенденцию к O (n).

4. Java 8 Stream

Используя функции Java 8, мы можем легко достичь того же результата более компактным и декларативным способом, используя методы Streamfilter anddistinct:

public static boolean checkStringForAllLetterUsingStream(String input) {
    long c = input.toLowerCase().chars()
      .filter(ch -> ch >= 'a' && ch <= 'z')
      .distinct()
      .count();
    return c == 26;
}

Big-O-сложность этого подхода также будет O (n).

4. тестирование

Давайте проверим удачный путь для нашего алгоритма:

@Test
public void givenString_whenContainsAllCharacter_thenTrue() {
    String sentence = "Farmer jack realized that big yellow quilts were expensive";
    assertTrue(EnglishAlphabetLetters.checkStringForAllTheLetters(sentence));
}

Здесьsentence содержит все буквы алфавита, поэтому в результате мы ожидаемtrue.

5. Заключение

В этом руководстве мы рассказали, как проверить, содержит ли строка все буквы алфавита. .

Мы увидели несколько способов реализовать это сначала, используя традиционное императивное программирование, регулярные выражения и потоки Java 8.

Добавить комментарий