使用Java查找字符串中的重复字符并计算出现次数

13

如何在一个字符串中找到一个字符出现的次数?

例如:The quick brown fox jumped over the lazy dog。

以下是一些示例输出:

'a' = 1
'o' = 4
'space' = 8
'.' = 1

10
你尝试过什么? - Azodious
11
这是一份作业吗? - Thinhbk
34个回答

29

如果你想处理的是字符串 s,那么你可以使用以下代码:

Map<Character,Integer> map = new HashMap<Character,Integer>();
for (int i = 0; i < s.length(); i++) {
  char c = s.charAt(i);
  if (map.containsKey(c)) {
    int cnt = map.get(c);
    map.put(c, ++cnt);
  } else {
    map.put(c, 1);
  }
}

请注意,它会计算所有字符,而不仅仅是字母。


@AndrewLogvinov.. Map 没有 contains 方法。 - Rohit Jain
@RohitJain 当然,我是凭记忆写的。已经更正了。 - Andrew Logvinov
我尝试使用这个解决方案,但是我得到了一个“已经存在相同键的项”的错误。这样可以接受吗? - Kala J
Kala J,哈希映射不允许重复的键。第二个值应该只是替换先前的值。我喜欢这种解决方案的简单性。 - SomeTonyGuy
这种方法的时间复杂度与下面描述的两个for循环方法相比如何?哪一个在时间和空间复杂度方面更好? - Saurabh Oza
1
@SaurabhOza,这种方法更好,因为你只需要一次迭代字符串字符-O(n),而使用2个for循环平均需要迭代n/2次-O(n^2)。但是,您需要稍微多一点的内存来存储中间结果。 - Andrew Logvinov

16

Java 8的方式:

"The quick brown fox jumped over the lazy dog."
        .chars()
        .mapToObj(i -> (char) i)
        .collect(Collectors.groupingBy(Object::toString, Collectors.counting()));

10
 void Findrepeter(){
    String s="mmababctamantlslmag";
    int distinct = 0 ;

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

        for (int j = 0; j < s.length(); j++) {

            if(s.charAt(i)==s.charAt(j))
            {
                distinct++;

            }
        }   
        System.out.println(s.charAt(i)+"--"+distinct);
        String d=String.valueOf(s.charAt(i)).trim();
        s=s.replaceAll(d,"");
        distinct = 0;

    }

}

似乎相当低效,考虑使用 Map<String, Integer> 替代。另外,您的方法名称似乎有一个拼写错误。 - xlm
2
关于为什么这个程序效率低的说明:该程序的时间复杂度为O(n^2),对于n(字符串长度)太大是不可接受的。 - Quazi Irfan
我使用str ="ved prakash sharma"作为输入,但是没有得到实际输出,我的输出结果: v--1 d--1 p--1 a--4 s--2 --2 h--2 - Onic Team

7
import java.io.*;
public class CountChar 
{

    public static void main(String[] args) throws IOException
    {
      String ch;
      BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
      System.out.print("Enter the Statement:");
      ch=br.readLine();
      int count=0,len=0;
        do
        {  
          try
          {
          char name[]=ch.toCharArray();
              len=name.length;
              count=0;
              for(int j=0;j<len;j++)
               {
                  if((name[0]==name[j])&&((name[0]>=65&&name[0]<=91)||(name[0]>=97&&name[0]<=123))) 
                      count++;
               }
              if(count!=0)
                System.out.println(name[0]+" "+count+" Times");
              ch=ch.replace(""+name[0],"");          
          }
          catch(Exception ex){}
        }
        while(len!=1);
   }

}

输出

Enter the Statement:asdf23123sfsdf

a 1 Times

s 3 Times

d 2 Times

f 3 Times

6
更好的方法是创建一个Map来存储计数。这将是一个Map<Character, Integer>
您需要遍历字符串的每个字符,并检查它是否为字母。您可以使用Character#isAlphabetic方法进行检查。如果是alphabet,则增加Map中的计数。如果字符尚未在Map中,则将其添加为计数1
注意:-Character.isAlphabetic方法是Java 7中的新方法。如果您使用较旧版本,则应使用Character#isLetter
    String str = "asdfasdfafk asd234asda";
    Map<Character, Integer> charMap = new HashMap<Character, Integer>();
    char[] arr = str.toCharArray();

    for (char value: arr) {

       if (Character.isAlphabetic(value)) {
           if (charMap.containsKey(value)) {
               charMap.put(value, charMap.get(value) + 1);

           } else {
               charMap.put(value, 1);
           }
       }
    }

    System.out.println(charMap);

输出: -

{f=3, d=4, s=4, a=6, k=1}

顺便提一下,在Character中没有isAlphabetic() =) 至少在Java 6中是这样的。可能应该使用isLetter() - Andrew Logvinov
@AndrewLogvinov。已编辑帖子以引用该内容。谢谢 :) - Rohit Jain
@AndrewLogvinov。哈哈。是的,确实,Java的人们还没有停止工作 :) - Rohit Jain

4
在一个字符串中查找重复项:

示例1: 使用HashMap

public class a36 {
    public static void main(String[] args) {
        String a = "Gini Rani";
        fix(a);
    }//main
    public static void fix(String a ){
        Map<Character ,Integer> map = new HashMap<>();
        for (int i = 0; i <a.length() ; i++ ) {
        char ch = a.charAt(i);
                map.put(ch , map.getOrDefault(ch,0) +1 );
        }//for

       List<Character> list = new ArrayList<>();
       Set<Map.Entry<Character ,Integer> > entrySet = map.entrySet();

       for (  Map.Entry<Character ,Integer> entry : entrySet) {
             list.add( entry.getKey()  ); 

             System.out.printf(  " %s : %d %n" ,  entry.getKey(), entry.getValue()           );
       }//for
       System.out.println("Duplicate elements => " + list);

    }//fix
}

Example 2 : using Arrays.stream() in Java 8

public class a37 {
    public static void main(String[] args) {
        String aa = "Protijayi Gini";
        String[] stringarray = aa.split("");

    Map<String , Long> map =  Arrays.stream(stringarray)
        .collect(Collectors.groupingBy(c -> c , Collectors.counting()));
        map.forEach( (k, v) -> System.out.println(k + " : "+ v)        );
    }
}

4
如果您的字符串只包含字母,则可以使用类似以下的代码:

public class StringExample {
public static void main(String[] args) {
    String str = "abcdabghplhhnfl".toLowerCase();
    // create a integer array for 26 alphabets.
    // where index 0,1,2.. will be the container for frequency of a,b,c...
    Integer[] ar = new Integer[26];
    // fill the integer array with character frequency.
    for(int i=0;i<str.length();i++) {
        int j = str.charAt(i) -'a';
        if(ar[j]==null) {
            ar[j]= 1;
        }else {
            ar[j]+= 1;
        }
    }   
    // print only those alphabets having frequency greater then 1.
    for(int i=0;i<ar.length;i++) {
        if(ar[i]!=null && ar[i]>1) {
            char c = (char) (97+i);
            System.out.println("'"+c+"' comes "+ar[i]+" times.");
        }
    }
}
}

输出:

 'a' comes 2 times.
 'b' comes 2 times.
 'h' comes 3 times.
 'l' comes 2 times.

3

这是一种不使用任何集合的实现方式,复杂度为n级别。虽然已经接受的解决方案也很好,而且也不使用集合,但似乎它没有处理特殊字符的情况。

import java.util.Arrays;

public class DuplicateCharactersInString {
    public static void main(String[] args) {
        String string = "check duplicate charcters in string";
        string = string.toLowerCase();
        char[] charAr = string.toCharArray();
        Arrays.sort(charAr);
        for (int i = 1; i < charAr.length;) {
            int count = recursiveMethod(charAr, i, 1);
            if (count > 1) {
                System.out.println("'" + charAr[i] + "' comes " + count + " times");
                i = i + count;
            } else
                i++;
        }
    }

    public static int recursiveMethod(char[] charAr, int i, int count) {
        if (ifEquals(charAr[i - 1], charAr[i])) {
            count = count + recursiveMethod(charAr, ++i, count);
        }
        return count;
    }

    public static boolean ifEquals(char a, char b) {
        return a == b;
    }
}

输出结果:

' ' comes 4 times
'a' comes 2 times
'c' comes 5 times
'e' comes 3 times
'h' comes 2 times
'i' comes 3 times
'n' comes 2 times
'r' comes 3 times
's' comes 2 times
't' comes 3 times

2
public class dublicate 
{
public static void main(String...a)
{
    System.out.print("Enter the String");
    Scanner sc=new Scanner(System.in);
    String st=sc.nextLine();
    int [] ar=new int[256];
    for(int i=0;i<st.length();i++)
    {
        ar[st.charAt(i)]=ar[st.charAt(i)]+1;
    }
    for(int i=0;i<256;i++)
    {
        char ch=(char)i;
        if(ar[i]>0)
        {
            if(ar[i]==1)
            {
                System.out.print(ch);
            }
            else
            {
                System.out.print(ch+""+ar[i]);
            }
        }
    }

}
}

1

使用Google Guava的Multiset<String>

Multiset<String> wordsMultiset = HashMultiset.create();
wordsMultiset.addAll(words);
for(Multiset.Entry<E> entry:wordsMultiset.entrySet()){
     System.out.println(entry.getElement()+" - "+entry.getCount());
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接