Java 使用流将字符串中的字母映射到出现次数

Java 使用流将字符串中的字母映射到出现次数,java,lambda,java-stream,Java,Lambda,Java Stream,我有一个字符串s,我正在尝试使用流API将s中的每个字母映射到它在s中出现的次数。 例如,长颈鹿->{1,1,1,1,2,2,1} 我尝试使用的代码是: String s = "giraffe"; int[] occurences = s.chars().map(c -> count(s, c)).toArray(); public int count(String text, char ch) { return (int) text.chars().filt

我有一个字符串
s
,我正在尝试使用流API将
s
中的每个字母映射到它在
s
中出现的次数。
例如,
长颈鹿->{1,1,1,1,2,2,1}

我尝试使用的代码是:

String s = "giraffe";
int[] occurences = s.chars().map(c -> count(s, c)).toArray();

public int count(String text, char ch) {
    return (int) text.chars().filter(c -> c == ch).count();
}
但是我得到了不兼容的类型:在以
int[]occurrences=…

我试过一些不同的变体,但都不起作用。有什么想法吗?谢谢

我修改了您的
count
方法,以接受
int
,而不是
char
,它可以工作

import java.util.Arrays;
class Main {
  public static void main(String[] args) {
    
    String s = "giraffe";
int[] occurences = s.chars().map(c -> count(s, c)).toArray();

 System.out.println(Arrays.toString(occurences));


  }
  public static int count(String text, int ch) {
    return (int) text.chars().filter(c -> c == ch).count();
}
}

请参见使用循环,我会这样做

  • 分配一个数组以容纳所有字符
  • 然后只打印非零的

有很多方法可以做到这一点。其中一种方法是使用
\X
作为正则表达式,由捕获的
匹配器
组指定和分组

演示:

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.regex.MatchResult;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Main {
    public static void main(String[] args) {
        // Test
        Stream.of(
                    "giraffe", 
                    "He

The problem

The real cause of your problem is that there isn’t any
CharStream
class. For this reason
s.chars()
gives you an
IntStream
. For this reason in turn in
map(c -> count(s, c))
,
c
has type
int
. So you are trying to pass an
int
to your
count
method where it expects a
char
. This gives you your error message. An
int
can be converted to a
char
, but some bits will be discarded, which is why the conversion is necessarily lossy.

The two obvious solutions

Solution 1: Tell Java that you mean to make this lossy conversion. Since you know that
c
comes from a
char
from your string, converting it back to a
char
again won’t do any harm.

    int[] occurences = s.chars().map(c -> count(s, (char) c)).toArray();
import java.util.LinkedHashMap;
导入java.util.Map;
导入java.util.regex.MatchResult;
导入java.util.regex.Pattern;
导入java.util.stream.collector;
导入java.util.stream.stream;
公共班机{
公共静态void main(字符串[]args){
//试验
溪流(
“长颈鹿”,
“问题是什么
问题的真正原因是没有任何
CharStream
类。因此
s.chars()
为您提供了一个
IntStream
。因此,依次在
map(c->count(s,c))中
c
的类型为
int
。因此,您试图将
int
传递给
count
方法,该方法需要
char
。这会给您错误消息。
int
可以转换为
char
,但会丢弃一些位,这就是转换必然有损的原因

两个显而易见的解决方案 解决方案1:告诉Java您打算进行这种有损转换。因为您知道
c
来自字符串中的
char
,所以再次将其转换回
char
不会造成任何伤害

public int count(String text, int ch) {
解决方案2:

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.regex.MatchResult;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Main {
    public static void main(String[] args) {
        // Test
        Stream.of(
                    "giraffe", 
                    "He

The problem

The real cause of your problem is that there isn’t any
CharStream
class. For this reason
s.chars()
gives you an
IntStream
. For this reason in turn in
map(c -> count(s, c))
,
c
has type
int
. So you are trying to pass an
int
to your
count
method where it expects a
char
. This gives you your error message. An
int
can be converted to a
char
, but some bits will be discarded, which is why the conversion is necessarily lossy.

The two obvious solutions

Solution 1: Tell Java that you mean to make this lossy conversion. Since you know that
c
comes from a
char
from your string, converting it back to a
char
again won’t do any harm.

    int[] occurences = s.chars().map(c -> count(s, (char) c)).toArray();
您可以声明您的方法以接受
int

public static Map<Character, Integer> histogram(String str) {
    Map<Character, Integer> map = new TreeMap<>();

    for (int i = 0; i < str.length(); i++) {
        char ch = Character.toLowerCase(str.charAt(i));
        map.put(ch, map.getOrDefault(ch, 0) + 1);
    }

    return map;
}
现在不需要转换(cast)。比较
c==ch
仍然可以正常工作。它无论如何都在比较两个
int
s,因此不会造成任何伤害


PS在其他答案中还有其他很好的解决方案和改进。就我个人而言,我会尝试将字符串预处理为计数映射,这样我就不必为每个字母再次计数。这不是必需的,您的代码只需进行上述两个更改中的一个即可正常工作。

对不起,但我认为
不适合这样做。简单的方法是使用
Map

公共静态地图直方图(字符串str){
Map Map=newtreemap();
对于(int i=0;i
非常棒的详细答案。谢谢,我没有意识到问题是由于
c
被转换为int
public int count(String text, int ch) {
public static Map<Character, Integer> histogram(String str) {
    Map<Character, Integer> map = new TreeMap<>();

    for (int i = 0; i < str.length(); i++) {
        char ch = Character.toLowerCase(str.charAt(i));
        map.put(ch, map.getOrDefault(ch, 0) + 1);
    }

    return map;
}