【问题标题】:How can I check if a single character appears in a string?如何检查单个字符是否出现在字符串中?
【发布时间】:2010-10-05 02:25:43
【问题描述】:

在 Java 中有没有办法检查条件:

"这个单个字符是否出现在字符串 x 中"

使用循环?

【问题讨论】:

  • 您有什么特别的原因要避免循环吗?
  • 您不能在没有循环的情况下对字符进行一般搜索。查看图灵机的工作原理。
  • 我们应该假设@barfoon 不希望循环出现在他们的代码中。显然机器在某处做了一个循环。否则这个问题是无稽之谈。
  • 我会说java的字符串操作非常有限
  • @barfoon,根据single character 的定义以及用户访问该字符的方式,可能会有不同的使用模式。我添加了an answer

标签: java validation string character


【解决方案1】:

您可以使用string.indexOf('a')

如果a 存在于string 中:

它返回字符第一次出现的索引 此对象表示的字符序列,如果 字符不出现。

【讨论】:

  • 但是这个调用后面总是有一个循环,因为否则你找不到符号。
  • indexOf() 在内部使用循环。
  • Barfoon 不是这么问的。 B 希望避免在 B 的代码中执行循环。当然,在 String 是一个包含许多有用方法的漂亮类中的字符数组之后,API 需要执行一个循环。
  • 这些答案如何获得如此多的支持?使用indexOf() 的解决方案在内部使用循环。没有一个答案给出了正确的解决方案,如果有人敢于提出新问题,人们将其声明为Duplicate。真令人失望;(
  • @PrashantPrabhakarSingh 我不明白如何在没有循环的情况下做到这一点。字符串或多或少是一组字符。如果它是一个组(集合、数组等),那么无论它是本地代码的内部还是外部,我都希望您需要一个循环才能在“组”中找到某些东西。我相信“不使用循环?”更像是“不写自己的循环?”。
【解决方案2】:
  • String.contains() 检查字符串是否包含指定的 char 值序列
  • String.indexOf() 返回指定字符或子字符串第一次出现的字符串中的索引(此方法有 4 种变体)

【讨论】:

  • a char 不是 CharSequence,因此不能传递给 String.contains(CharSequence)。
  • 要将 String.contains() 与单个字符 c 一起使用,请执行以下操作:String.contains(Character.toString(c))
  • 如果你喜欢短代码,也可以这样做:String.contains(""+c)
【解决方案3】:

我不确定原始发帖人到底在问什么。由于 indexOf(...) 和 contains(...) 都可能在内部使用循环,也许他想看看这是否可能在没有循环的情况下实现?我可以想到两种方法,一种当然是递归:

public boolean containsChar(String s, char search) {
    if (s.length() == 0)
        return false;
    else
        return s.charAt(0) == search || containsChar(s.substring(1), search);
}

另一个远没有那么优雅,但完整性......:

/**
 * Works for strings of up to 5 characters
 */
public boolean containsChar(String s, char search) {
    if (s.length() > 5) throw IllegalArgumentException();

    try {
        if (s.charAt(0) == search) return true;
        if (s.charAt(1) == search) return true;
        if (s.charAt(2) == search) return true;
        if (s.charAt(3) == search) return true;
        if (s.charAt(4) == search) return true;
    } catch (IndexOutOfBoundsException e) {
        // this should never happen...
        return false;
    }
    return false;
}

当然,随着您需要支持越来越长的字符串,行数会增加。但是根本没有循环/递归。如果您担心 length() 使用循环,您甚至可以删除长度检查。

【讨论】:

  • 如果您将递归定义为非循环过程,那么您就是一个极客 :D +1 有创意。
  • 硬编码长度为 5 一切都好。否则需要做一个循环来搜索字符。不是迂腐,而是图灵机的定义证明了这一点。计算设备的基础。
  • 如果我错了,请纠正我,我觉得归根结底,递归是变相的循环,不是吗?在某些情况下,它可能会导致比普通循环更多的内存消耗。
【解决方案4】:
String temp = "abcdefghi";
if(temp.indexOf("b")!=-1)
{
   System.out.println("there is 'b' in temp string");
}
else
{
   System.out.println("there is no 'b' in temp string");
}

【讨论】:

  • 这不是已接受答案的完全相同吗?我们承认您的努力,但您应该尝试找到一些未回答的问题并回答它们。
【解决方案5】:

您可以使用String 类中的两种方法。

  • String.contains() 检查字符串是否包含指定的 char 值序列
  • String.indexOf() 返回指定字符或子字符串第一次出现的字符串中的索引,如果未找到该字符,则返回 -1(此方法有 4 种变体)

方法一:

String myString = "foobar";
if (myString.contains("x") {
    // Do something.
}

方法二:

String myString = "foobar";
if (myString.indexOf("x") >= 0 {
    // Do something.
}

链接:Zach Scrivena

【讨论】:

    【解决方案6】:

    如果您需要经常检查相同的字符串,您可以预先计算出现的字符。这是一个使用包含在长数组中的位数组的实现:

    public class FastCharacterInStringChecker implements Serializable {
    private static final long serialVersionUID = 1L;
    
    private final long[] l = new long[1024]; // 65536 / 64 = 1024
    
    public FastCharacterInStringChecker(final String string) {
        for (final char c: string.toCharArray()) {
            final int index = c >> 6;
            final int value = c - (index << 6);
            l[index] |= 1L << value;
        }
    }
    
    public boolean contains(final char c) {
        final int index = c >> 6; // c / 64
        final int value = c - (index << 6); // c - (index * 64)
        return (l[index] & (1L << value)) != 0;
    }}
    

    【讨论】:

    • 我在我遇到的类似问题上尝试了您的解决方案。我最接近的解决方案是 string1 长度 63k 和 string2 长度 95k 超过 1500 毫秒。您的解决方案会在 3-5 毫秒内输出结果。您能否编辑您的解决方案以包含解释?请问?
    【解决方案7】:

    要检查字符串中是否不存在某些内容,您至少需要查看字符串中的每个字符。因此,即使您没有明确使用循环,它也将具有相同的效率。话虽如此,您可以尝试使用 str.contains(""+char)。

    【讨论】:

    • 同意。在某个时候,某个地方的某个人需要构建一个循环来执行此操作。幸运的是 Java API 可以做到这一点,否则我们的代码会非常混乱!
    【解决方案8】:

    是的,使用字符串类的 indexOf() 方法。 See the API documentation for this method

    【讨论】:

      【解决方案9】:

      下面是你要找的吗?

      int index = string.indexOf(character);
      return index != -1;
      

      【讨论】:

      • 你为什么有&amp;&amp; string.lastIndexOf(character) != index
      【解决方案10】:
      package com;
      public class _index {
      
          public static void main(String[] args) {
              String s1="be proud to be an indian";
              char ch=s1.charAt(s1.indexOf('e'));
              int count = 0; 
              for(int i=0;i<s1.length();i++) {
                  if(s1.charAt(i)=='e'){
                      System.out.println("number of E:=="+ch);
                      count++;
                  }
              }
              System.out.println("Total count of E:=="+count);
          }
      }
      

      【讨论】:

      • for 现在不是循环了吗?
      【解决方案11】:

      如果你在JAVA中看到indexOf的源码:

      public int indexOf(int ch, int fromIndex) {
      
              final int max = value.length;
      
              if (fromIndex < 0) {
      
                  fromIndex = 0;
      
              } else if (fromIndex >= max) {
      
                  // Note: fromIndex might be near -1>>>1.
      
                  return -1;
      
              }
      
      
              if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
      
                  // handle most cases here (ch is a BMP code point or a
      
                  // negative value (invalid code point))
      
                  final char[] value = this.value;
      
                  for (int i = fromIndex; i < max; i++) {
      
                      if (value[i] == ch) {
      
                          return i;
      
                      }
      
                  }
      
                  return -1;
      
              } else {
      
                  return indexOfSupplementary(ch, fromIndex);
      
              }
      
          }
      

      您可以看到它使用 for 循环来查找字符。请注意,您可能在代码中使用的每个 indexOf 都等于一个循环。

      因此,对单个字符使用循环是不可避免的。

      但是,如果您想找到具有更多不同形式的特殊字符串,请使用有用的库,例如util.regex,它会部署更强大的算法来匹配字符或字符串模式与正则表达式。例如在字符串中查找电子邮件:

      String regex = "^(.+)@(.+)$";
       
      Pattern pattern = Pattern.compile(regex);
      Matcher matcher = pattern.matcher(email);
      

      如果您不喜欢使用正则表达式,只需使用循环和charAt 并尝试在一个循环中涵盖所有情况。

      小心递归方法比循环有更多的开销,所以不推荐。

      【讨论】:

        【解决方案12】:

        String.contains(String)String.indexOf(String) - 建议

        "abc".contains("Z"); // false - correct
        "zzzz".contains("Z"); // false - correct
        "Z".contains("Z"); // true - correct
        "?and?".contains("?"); // true - correct
        "?and?".contains("?"); // false - correct
        "?and?".indexOf("?"); // 0 - correct
        "?and?".indexOf("?"); // -1 - correct
        

        String.indexOf(int) 并仔细考虑 String.indexOf(char) 与 char 到 int 加宽

        "?and?".indexOf("?".charAt(0)); // 0 though incorrect usage has correct output due to portion of correct data
        "?and?".indexOf("?".charAt(0)); // 0 -- incorrect usage and ambiguous result
        "?and?".indexOf("?".codePointAt(0)); // -1 -- correct usage and correct output
        

        Java 世界中关于字符的讨论是模棱两可的

        charCharacter 的值是否可以视为单个字符?

        。在 unicode 字符的上下文中,charCharacter 有时可以是 part of a single character,在逻辑上不应视为 a complete single character

        如果不是,什么应该被视为单个字符(逻辑上)?

        任何支持 Unicode 字符的字符编码的系统都应将 unicode 的代码点视为单个字符。

        因此,Java 应该非常清晰和响亮地做到这一点,而不是向用户公开过多的内部实现细节。

        String 类不擅长抽象(尽管它需要大量令人困惑的understanding of its encapsulations to understand the abstraction ???,因此需要anti-pattern)。

        它与一般的char 用法有何不同?

        char 只能映射到基本多语言平面中的一个字符。

        只有codePoint - int 可以覆盖整个Unicode 字符范围。

        为什么会有这种差异?

        char 在内部被视为 16-bit 无符号值,并且无法使用仅使用 2-bytes 的 UTF-16 内部表示来表示所有 unicode 字符。有时,16-bit 范围内的值必须与另一个 16-bit 值组合才能正确定义字符。

        不用太冗长,indexOfcharAtlength 等方法的用法应该更明确。真诚地希望 Java 能够添加具有明确定义抽象的新 UnicodeStringUnicodeCharacter 类。

        喜欢contains 而不是indexOf(int) 的原因

        1. 实际上有许多代码流将逻辑字符视为 java 中的char
        2. 在 Unicode 上下文中,char 是不够的
        3. 虽然indexOf 接受intcharint 的转换掩盖了用户,用户可能会执行类似str.indexOf(someotherstr.charAt(0)) 的操作(除非用户知道确切的上下文)李>
        4. 因此,将所有内容都视为CharSequence(又名String)会更好
            public static void main(String[] args) {
                System.out.println("?and?".indexOf("?".charAt(0))); // 0 though incorrect usage has correct output due to portion of correct data
                System.out.println("?and?".indexOf("?".charAt(0))); // 0 -- incorrect usage and ambiguous result
                System.out.println("?and?".indexOf("?".codePointAt(0))); // -1 -- correct usage and correct output
                System.out.println("?and?".contains("?")); // true - correct
                System.out.println("?and?".contains("?")); // false - correct
            }
        

        语义

        1. char 可以处理大部分实际用例。仍然最好在编程环境中使用代码点以实现未来的可扩展性。
        2. codepoint 应该可以处理几乎所有与编码相关的技术用例。
        3. 不过,Grapheme Clusters 超出了codepoint 抽象级别的范围。
        4. 如果ints太贵(翻倍),存储层可以选择char接口。除非存储成本是唯一的指标,否则最好使用codepoint。此外,最好将存储视为byte,并将语义委托给围绕存储构建的业务逻辑。
        5. 语义可以在多个级别进行抽象。 codepoint 应该成为最低级别的接口,其他语义可以在运行时环境中围绕codepoint 构建。

        【讨论】:

        • 这是一个非常愉快的答案:)
        【解决方案13】:
        static String removeOccurences(String a, String b)
        {
            StringBuilder s2 = new StringBuilder(a);
        
            for(int i=0;i<b.length();i++){
                char ch = b.charAt(i);  
                System.out.println(ch+"  first index"+a.indexOf(ch));
        
                int lastind = a.lastIndexOf(ch);
        
            for(int k=new String(s2).indexOf(ch);k > 0;k=new String(s2).indexOf(ch)){
                    if(s2.charAt(k) == ch){
                        s2.deleteCharAt(k);
                System.out.println("val of s2 :             "+s2.toString());
                    }
                }
              }
        
            System.out.println(s1.toString());
        
            return (s1.toString());
        }
        

        【讨论】:

        • 这里我们正在寻找字符串 a 中存在的字符串 b 中的每个字符的出现并删除这些字符。
        【解决方案14】:
        you can use this code. It will check the char is present or not. If it is present then the return value is >= 0 otherwise it's -1. Here I am printing alphabets that is not present in the input.
        
        import java.util.Scanner;
        
        public class Test {
        
        public static void letters()
        {
            System.out.println("Enter input char");
            Scanner sc = new Scanner(System.in);
            String input = sc.next();
            System.out.println("Output : ");
            for (char alphabet = 'A'; alphabet <= 'Z'; alphabet++) {
                    if(input.toUpperCase().indexOf(alphabet) < 0) 
                        System.out.print(alphabet + " ");
            }
        }
        public static void main(String[] args) {
            letters();
        }
        

        }

        //Ouput Example
        Enter input char
        nandu
        Output : 
        B C E F G H I J K L M O P Q R S T V W X Y Z
        

        【讨论】:

        • 请不要把解释放在代码块里
        【解决方案15】:

        如果不使用循环/递归至少遍历字符串一次,您将无法检查 char 是否出现在某个字符串中(像 indexOf 这样的内置方法也使用循环)

        如果没有。如果字符在字符串 x 中,您查找的次数比我建议使用 Set 数据结构的字符串长度要长得多,因为这比简单地使用 @ 更有效987654322@

        String s = "abc";
        
        // Build a set so we can check if character exists in constant time O(1)
        Set<Character> set = new HashSet<>();
        int len = s.length();
        for(int i = 0; i < len; i++) set.add(s.charAt(i));
        
        // Now we can check without the need of a loop
        // contains method of set doesn't use a loop unlike string's contains method
        set.contains('a') // true
        set.contains('z') // false
        

        使用 set 您将能够在 恒定时间 O(1) 内检查字符串中是否存在字符,但您还将使用额外的内存(空间复杂度将为 O(n) )。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-05-31
          • 2022-12-14
          • 2012-05-25
          • 2019-12-03
          • 2017-07-22
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多