【发布时间】:2011-04-24 22:02:51
【问题描述】:
我需要来自String 对象的Iterator<Character>。 Java 中是否有任何可用函数可以为我提供此功能,还是我必须自己编写代码?
【问题讨论】:
我需要来自String 对象的Iterator<Character>。 Java 中是否有任何可用函数可以为我提供此功能,还是我必须自己编写代码?
【问题讨论】:
这感觉很脏,但你可以使用带有空字符串分隔符的 Scanner:
Scanner scanner = new java.util.Scanner(myInput).useDelimiter("");
Scanner 实现了Iterator,因此scanner 现在是长度为1 的字符串的Iterator,这很接近。
要继续(非常?)脏,在 Java 8 中,您可以这样做以简洁地按字符进行迭代:
for (String s: (Iterable<String>)() -> scanner) {
char c = s.charAt(0);
System.out.println(c);
}
如需详细了解 () -> scanner 为何有效(以及为什么它可能很危险,但在此用例中不适用),请参阅 Explain how this lambda can be assigned to an Iterable。
【讨论】:
使用 java 8 或更高版本,您可以使用流工具。使用chars() 方法,您可以访问IntStream。 IntStream 支持返回 OfInt 迭代器的方法 iterator()。 OfInt 实现 Iterator<Integer>。
String str = "foobar";
OfInt ofit = str.chars().iterator();
Iterator<Integer> it = ofit;
这不是一个完美的答案,因为您要求 Iterator
顺便说一句:使用 str.codePoints() 您还可以访问代码点 IntStream。
【讨论】:
for (char c : myString.toCharArray()) {
}
【讨论】:
char[] 仍然不能分配给 Iterable<Character>。
这可以在 Apache Commons Lang 的帮助下完成(如果您不想使用 Guava,并且想要一个真正的 java.util.Iterator。
private static Iterator<Character> iterator(String string) {
return Arrays.asList(ArrayUtils.toObject(string.toCharArray())).iterator();
}
【讨论】:
在另一个答案中从其他人那里窃取,这可能是最好的直接实现(如果您不打算使用番石榴)。
/**
* @param string
* @return list of characters in the string
*/
public static List<Character> characters(final String string) {
return new AbstractList<Character>() {
@Override
public Character get(int index) {
return string.charAt(index);
}
@Override
public int size() {
return string.length();
}
};
}
【讨论】:
简答: 不,你必须编码。
长答案: List 和 Set 都有一个获取Iterator 的方法(还有一些其他的集合类,但可能不是您想要的)。 List 和 Set 接口是 Collections Framework 的一部分,它只允许添加/删除/迭代像 Character 或 Integer 这样的对象(而不是像 char 或 int 这样的基元)。 Java 1.5 called auto-boxing 中有一个功能可以隐藏这个原语到对象的转换,但我不推荐它,在这种情况下它不会提供你想要的。
另一种方法是将字符串包装在您自己的类中
implements Iterator<Character>
但这可能比它的价值更多。
这是一个代码 sn-p 用于做你想做的事情:
String s = "";
List<Character> list = new ArrayList<Character>(s.length());
for (int i = 0; i < s.length(); i++) {
// note that Character.valueOf() is preferred to new Character()
// you can omit the Character.valueOf() method
// and Java 1.5+ will auto-box the primitive into an Object
list.add(Character.valueOf(s.charAt(i)));
}
Iterator<Character> iterator = list.iterator();
【讨论】:
List 和 Set没有实现 Iterator。
Iterable 接口(它提供了一个iterator() 函数,它返回一个Iterator)所以没关系。但是您的代码效率低下,因为它创建了字符串的完整副本。
Iterator 合约明确允许不支持remove()。此外,除了 Iterator 之外,您也别无选择。
一种选择是使用Guava:
ImmutableList<Character> chars = Lists.charactersOf(someString);
UnmodifiableListIterator<Character> iter = chars.listIterator();
这会生成一个由给定字符串支持的不可变字符列表(不涉及复制)。
但是,如果您最终自己这样做,我建议不要像许多其他示例那样公开Iterator 的实现类。我建议改为创建自己的实用程序类并公开静态工厂方法:
public static Iterator<Character> stringIterator(final String string) {
// Ensure the error is found as soon as possible.
if (string == null)
throw new NullPointerException();
return new Iterator<Character>() {
private int index = 0;
public boolean hasNext() {
return index < string.length();
}
public Character next() {
/*
* Throw NoSuchElementException as defined by the Iterator contract,
* not IndexOutOfBoundsException.
*/
if (!hasNext())
throw new NoSuchElementException();
return string.charAt(index++);
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
【讨论】:
Iterator<Character>。
Iterator 不是Iterable(并且Character 不是CharSequence)。
没有直接的方法。不过,编码并不难:
public static Iterator<Character> gimmeIterator(final String x) {
Iterator<Character> it = new Iterator<Character>() {
String str = x == null ? "" : x;
int pos = -1; // last read
public boolean hasNext() { return(pos+1 < str.length()); }
public Character next() { pos++; return str.charAt(pos); }
public void remove() {
throw new UnsupportedOperationException("remove unsupported for this iterator");
}
};
return it;
}
【讨论】:
它不存在,但实现起来很简单:
class CharacterIterator implements Iterator<Character> {
private final String str;
private int pos = 0;
public CharacterIterator(String str) {
this.str = str;
}
public boolean hasNext() {
return pos < str.length();
}
public Character next() {
return str.charAt(pos++);
}
public void remove() {
throw new UnsupportedOperationException();
}
}
实现可能是最有效的。
【讨论】:
Iterator 迭代一个集合或任何实现它的东西。 String 类没有实现这个接口。所以没有直接的办法。
要遍历一个字符串,你必须首先从它创建一个 char 数组,然后从这个 char 数组创建一个 Collection。
【讨论】:
Iterator 只遍历集合是不正确的。 Iterator 是一个简单的接口,它可以迭代任何它实现的迭代。
不确定是否有更直接的方法,但您可以这样做;
Arrays.asList(string.toCharArray()).iterator();
从头开始; Arrays.asList 并没有像我记得的那样做。
编辑 2:似乎它在 1.4 中最后一次以这种方式工作
【讨论】:
Iterator<char[]>。
Arrays.asList(Object[]) 是编译器错误。当该方法(错误地)在 1.5 中更改为 varargs 方法时,将原始数组传递给它是合法的,但它并没有达到您的预期。
CharacterIterator it = new StringCharacterIterator("abcd");
// Iterate over the characters in the forward direction
for (char ch=it.first(); ch != CharacterIterator.DONE; ch=it.next())
// Iterate over the characters in the backward direction
for (char ch=it.last(); ch != CharacterIterator.DONE; ch=it.previous())
【讨论】:
Iterator<Character>,我真的只想要这样的东西。
Iterable 和Iterator 是一个非常糟糕的主意,不应该这样做。
iterator() 方法中返回this 是完全错误的并且违反了合同。