OMG, 12 изысканных советов по работе со строками в Java, изучите их

Java

Можно сказать, что String является самым представительным классом в Java. Кажется, что ни одного из них нет. Это как Li Jiaqi в индустрии прямых трансляций, Li Dan в ток-шоу и статус первоклассного старшего брата. Должен признаться, что в последнее время было много разглагольствований, и моя голова полна этих шуток. Писать статьи немного невольно. Право, я не могу удержаться.

Поскольку строки являются наиболее часто используемыми, это означает, что интервьюер хорош в этом и любит задавать некоторые навыки кодирования в строках, чтобы проверить, является ли кандидат технически квалифицирован и имеет прочный фундамент, верно?

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

01. Как получить разные символы и их количество в строке?

Эту задачу можно разбить на два шага: первый шаг — найти разные символы, а второй — подсчитать их количество. Кажется немного ерундой, не так ли? Итак, позвольте мне сначала дать вам ответ.

public class DistinctCharsCount {
    public static void main(String[] args) {
        printDistinctCharsWithCount("itwanger");
        printDistinctCharsWithCount("chenmowanger");
    }

    private static void printDistinctCharsWithCount(String input) {
        Map<Character, Integer> charsWithCountMap = new LinkedHashMap<>();

        for (char c : input.toCharArray()) {
            Integer oldValue = charsWithCountMap.get(c);

            int newValue = (oldValue == null) ? 1 :
                    Integer.sum(oldValue, 1);
            
            charsWithCountMap.put(c, newValue);
        }
        System.out.println(charsWithCountMap);
    }
}

Вывод программы:

{i=1, t=1, w=1, a=1, n=1, g=1, e=1, r=1}
{c=1, h=1, e=2, n=2, m=1, o=1, w=1, a=1, g=1, r=1}

Расскажи мне о моих мыслях:

1) объявитьLinkedHashMap, вы также можете использовать HashMap, но первый может сохранить порядок после разделения строки, и результат выглядит более ясным с первого взгляда.

Зачем использовать Карту? Поскольку ключ Map не может повторяться, количество повторяющихся символов может быть просто накоплено.

2) Разбить строку на символы и пройти по ней.

3) Если ключ нулевой, значит, его номер должен быть +1, иначе +1 к предыдущему значению, а затем снова помещается в Карту, таким образом перезаписывая предыдущее количество символов.

Идея ясна, не так ли? Я не мог не похвалить себя.

Что ж, после JDK 8 Map добавил очень мощный методmerge(), назначение нескольких клавиш одновременно:

private static void printDistinctCharsWithCountMerge(String input) {
    Map<Character, Integer> charsWithCountMap = new LinkedHashMap<>();

    for (char c : input.toCharArray()) {
        charsWithCountMap.merge(c, 1, Integer::sum);
    }
    System.out.println(charsWithCountMap);
}

Это здорово? Всего одна строка кода. Первый параметр — это ключ, второй параметр — это значение, а третий параметр — это BiFunction, что означает, что если ключ уже существует, новое значение будет пересчитано в соответствии с BiFunction.

Если символ встречается впервые, ему присваивается значение 1, в противном случае предыдущее значение суммируется с 1.

02. Как перевернуть строку?

Если учащиеся знакомы со StringBuilder и StringBuffer, этот вопрос будет очень простым и понятным.reverse()Все кончено, да?

public class ReverseAString {
    public static void main(String[] args) {
        reverseInputString("沉默王二");
    }
    private static void reverseInputString(String input) {
        StringBuilder sb = new StringBuilder(input);
        String result = sb.reverse().toString();
        System.out.println(result);
    }
}

Результат выглядит следующим образом:

二王默沉

Еще один момент, StringBuffer и StringBuilder очень похожи, первый синхронный, добавлены все публичные методыsynchronizedключевое слово, которое можно использовать в нескольких потоках; последний является асинхронным и не имеетsynchronizedКлючевые слова, поэтому в производительности, если нет параллельных требований, используйте StringBuilder.

03. Как определить, симметрична ли строка до и после?

Что это обозначает? Подобно струне, сложенной до и после, она симметрична. Это похоже на то, когда вы стоите перед зеркалом и видите себя с нефритовым деревом, обращенным к ветру, и луной, закрытой от стыда.

public class PalindromeString {
    public static void main(String[] args) {

        checkPalindromeString("沉默王二");
        checkPalindromeString("沉默王二 二王默沉");
    }

    private static void checkPalindromeString(String input) {
        boolean result = true;
        int length = input.length();
        for (int i = 0; i < length / 2; i++) {
            if (input.charAt(i) != input.charAt(length - i - 1)) {
                result = false;
                break;
            }
        }
        System.out.println(input + " 对称吗? " + result);

    }
}

Результат выглядит следующим образом:

沉默王二 对称吗? false
沉默王二 二王默沉 对称吗? true

Расскажи мне о моей идее: судить о том, симметрична ли строка после сложения пополам, очень просто, разбивается от середины, первый символ сравнивается с последним символом, и как только найден неравный, возвращается false.

Обратите внимание на три момента:

1) Индекс цикла for начинается с 0 и идет кlength/2Заканчивать.

2) Нижний индекс i и длина-i-1 симметричны.

3) break раз ложный.

04. Как удалить все вхождения указанных символов?

Строковый класс не указанremove()метод, но обеспечиваетreplaceAll()метод, вы можете сделать это, заменив указанные символы пробелами, верно?

public class RemoveCharFromString {
    public static void main(String[] args) {
        removeCharFromString("沉默王二", '二');
        removeCharFromString("chenmowanger", 'n');

    }

    private static void removeCharFromString(String input, char c) {
        String result = input.replaceAll(String.valueOf(c), "");
        System.out.println(result);
    }
}

Результат выглядит следующим образом:

沉默王
chemowager

05, как доказать, что строка не является переменной?

Я написал две статьи о неизменности строк, и в конце меня стошнит. Но все еще есть некоторые одноклассники, которые не понимают, и люди время от времени присылают мне личные сообщения, поэтому я должен добавить предыдущую статью в избранное, и когда я попрошу, я отправлю ему ссылку.

Есть много факторов, которые вызывают эту путаницу, например, передача Java по значению или по ссылке? Что такое пул строковых констант?

На этот раз я должен говорить об этом снова, хоть я и устал, но мне еще нужно это доказать!

public class StringImmutabilityTest {
    public static void main(String[] args) {
        String s1 = "沉默王二";
        String s2 = s1;
        System.out.println(s1 == s2);

        s1 = "沉默王三";
        System.out.println(s1 == s2);

        System.out.println(s2);
    }
}

Результат выглядит следующим образом:

true
false
沉默王二

1)String s1 = "沉默王二", Java создает объект строки «Silent King II» в пуле строковых констант и присваивает адресную ссылку s1.

2)String s2 = s1, s2 и s1 указывают на одну и ту же адресную ссылку — «тихий король два» в пуле констант.

Итак, s1 == s2 верно в это время.

3) s1 = "沉默王三", Java создает строку символов «Silent King Three» в пуле строковых констант и присваивает адресную ссылку s1, но s2 по-прежнему указывает на адресную ссылку строки символов «Silent King Two».

Следовательно, в настоящее время s1 == s2 ложно, а выходным результатом s2 является «Silent King II», что доказывает, что строка неизменяема.

06. Как посчитать количество слов в строке?

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

public class CountNumberOfWordsInString {
    public static void main(String[] args) {
        countNumberOfWords("My name is Wanger");
        countNumberOfWords("I Love Java Programming");
        countNumberOfWords(" Java	is  very   important ");
    }

    private static void countNumberOfWords(String line) {
        String trimmedLine = line.trim();
        int count = trimmedLine.isEmpty() ? 0 : trimmedLine.split("\\s+").length;

        System.out.println(count);
    }
}

Результат выглядит следующим образом:

4
4
4

split()Метод может разбивать строку, а параметром могут быть не только пробелы, но и пробельные символы (несколько пробелов, табуляции), которые можно заменить регулярными выражениями; возвращаемый массив, черезlengthВы можете получить количество слов.

если правильноsplit()Если вам интересен этот метод, вы можете прочитать статью, которую я написал ранее, очень полную и насыщенную.

Эй, разделить строку так сложно

07, как вы проверяете символы в обеих строках?

Как понять этот вопрос? Например, в строках «Молчаливый Ван Эр» и «Шэнь Ван Эрмо» используются одни и те же символы, верно? Например, символы, используемые в строках «Silent King 2» и «Silent King 3», разные, понимаете?

public class CheckSameCharsInString {
    public static void main(String[] args) {
        sameCharsStrings("沉默王二", "沉王二默");
        sameCharsStrings("沉默王二", "沉默王三");
    }

    private static void sameCharsStrings(String s1, String s2) {
        Set<Character> set1 = s1.chars().mapToObj(c -> (char) c).collect(Collectors.toSet());
        System.out.println(set1);
        Set<Character> set2 = s2.chars().mapToObj(c -> (char) c).collect(Collectors.toSet());
        System.out.println(set2);
        System.out.println(set1.equals(set2));
    }
}

Результат выглядит следующим образом:

[默, 沉, 王, 二]
[默, 沉, 王, 二]
true
[默, 沉, 王, 二]
[默, 沉, 三, 王]
false

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

08. Как определить, что строка содержит другую строку?

Этот вопрос немного прост, не так ли? В предыдущем вопросе также использовался поток, поэтому этот вопрос будет отправлен напрямую? Не сомневайтесь в себе, просто используйте класс stringcontains()метод.

public class StringContainsSubstring {
    public static void main(String[] args) {
        String s1 = "沉默王二";
        String s2 = "沉默";

        System.out.println(s1.contains(s2));
    }
}

Результат выглядит следующим образом:

true

contains()Метод фактически вызываетindexOf()метод:

public boolean contains(CharSequence s) {
    return indexOf(s.toString()) >= 0;
}

09. Как поменять местами две строки без использования третьей переменной?

Этот вопрос довольно интересен, не так ли? Особенно предварительное условие, третья переменная не используется.

public class SwapTwoStrings {
    public static void main(String[] args) {
        String s1 = "沉默";
        String s2 = "王二";

        s1 = s1.concat(s2);
        s2 = s1.substring(0,s1.length()-s2.length());
        s1 = s1.substring(s2.length());

        System.out.println(s1);
        System.out.println(s2);
    }
}

Результат выглядит следующим образом:

王二
沉默

Расскажи мне о моих мыслях:

1) пройтиconcat()метод объединяет две строки вместе.

2) тогда проходитеsubstring()метод для извлечения второй строки и первой строки соответственно.

10. Как найти первый уникальный символ в строке?

Давай, давайте разберемся с этой проблемой на примере. Например, в строке «Silent Wang Shen Silent Er» первым неповторяющимся символом будет «王», верно? Поскольку повторяется «Шэнь», повторяется «Молчание».

public class FindNonRepeatingChar {
    public static void main(String[] args) {
        System.out.println(printFirstNonRepeatingChar("沉默王沉沉默二"));
        System.out.println(printFirstNonRepeatingChar("沉默王沉"));
        System.out.println(printFirstNonRepeatingChar("沉沉沉"));
    }

    private static Character printFirstNonRepeatingChar(String string) {
        char[] chars = string.toCharArray();

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

        for (int i = 0; i < chars.length; i++) {
            char c = chars[i];

            if (discardedChars.contains(c))
                continue;

            for (int j = i + 1; j < chars.length; j++) {
                if (c == chars[j]) {
                    discardedChars.add(c);
                    break;
                } else if (j == chars.length - 1) {
                    return c;
                }
            }
        }
        return null;
    }
}

Результат выглядит следующим образом:

王
默
null

Расскажи мне о моих мыслях:

1) Разбить строку на массивы символов.

2) Объявите список и поместите в него повторяющиеся символы.

3) Внешний цикл for начинается с первого символа и, если он уже есть в списке, продолжается до следующего раунда.

4) Вложенные циклы for, начиная с первого символа и заканчивая следующим символом (j = i + 1) для запуска обхода, если находит повторяющийся символ с предыдущим символом, он добавляется в Список и выпрыгивает из внутреннего цикла; если находит последний (j == chars.length - 1) тоже не найден, ведь это первый неповторяющийся символ, верно?

11. Как проверить, что строка состоит только из цифр?

Есть очень глупое решение, которое заключается в использованииLong.parseLong(string)Если строку нельзя преобразовать в целое число, она должна содержать не только числа, верно?

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

public class CheckIfStringContainsDigitsOnly {
    public static void main(String[] args) {
        digitsOnlyString("123 沉默王二");
        digitsOnlyString("123");

    }

    private static void digitsOnlyString(String string) {
        if (string.matches("\\d+")) {
            System.out.println("只包含数字的字符串:" + string);
        }
    }
}

Результат выглядит следующим образом:

只包含数字:123

12. Как реализовать глубокую копию строки?

Поскольку строки неизменяемы, вы можете напрямую использовать оператор «=» для копирования одной строки в другую, не затрагивая друг друга.

public class JavaStringCopy {
    public static void main(String args[]) {
        String str = "沉默王二";
        String strCopy = str;

        str = "沉默王三";
        System.out.println(strCopy);
    }
}

Результат выглядит следующим образом:

沉默王二

Этот пример почти такой же, как и предыдущий, где строки были неизменяемыми, верно? Это действительно потому, что строки неизменяемы.Если это изменяемый объект, следует обратить внимание на глубокое копирование.Лучше использовать новое ключевое слово для возврата нового объекта.

public Book getBook() {
    Book clone = new Book();
    clone.setPrice(this.book.getPrice());
    clone.setName(this.book.getName());
    return clone;
}

Что касается неизменяемых объектов, перейдите по ссылке ниже, чтобы увидеть статью, которую я написал ранее.

На этот раз, если я не понимаю неизменный класс, я сделаю

Наконец

Я надеюсь, что эти 12 деликатных советов по работе со струнами помогут вам закрепить фундамент волны. В любом случае, я сам повторно закрепил волну, и это очень полезно. Такое ощущение, что "группа эльфов танцует у меня в голове", научитесь это правильно!


Я Безмолвный Король Эр, программист, выживший в Лояне, древней столице девяти династий.Подпишитесь, чтобы повысить эффективность обучения, спасибо за вашу поддержку три раза подряд, Олли 🌹.

Примечание. Если в статье есть какие-либо проблемы, пожалуйста, исправьте их.

Если вы считаете, что статья полезна для вас, добро пожаловать в поиск WeChat »Тихий король 2"Прочтите в первый раз, ответьте на ключевое слово"нуб«Вы можете бесплатно получить версию 2.0 «Java Xiaobai от новичка до самонадеянного» с более чем 40 000 слов моей печени; эта статьяGitHub github.com/itwangerОн был записан, добро пожаловать в звезду.