我需要将java中的一个String从“aaaaaaaa”增加到“aaaaaab”到“aaaaaac”,然后最后到“aaaaaaba”到“aaaaaabb”等等。
这有诀窍吗?
答案 0 :(得分:53)
你基本上实现了一个带有“零”(“a”)的Base 26 number system。
你这样做的方式与将int转换为base-2或base-10 String的方式相同,但是使用26而不是'0'作为基础,而不是使用2或10,你使用'a'
在Java中,您可以轻松使用它:
public static String base26(int num) {
if (num < 0) {
throw new IllegalArgumentException("Only positive numbers are supported");
}
StringBuilder s = new StringBuilder("aaaaaaa");
for (int pos = 6; pos >= 0 && num > 0 ; pos--) {
char digit = (char) ('a' + num % 26);
s.setCharAt(pos, digit);
num = num / 26;
}
return s.toString();
}
然后基本的想法是不存储String,而只是存储一些计数器(int为int或long,具体取决于您的要求)并根据需要将其转换为String。这样,您可以轻松地增加/减少/修改计数器,而无需解析和重新创建字符串。
答案 1 :(得分:13)
下面的代码使用递归方法来获取下一个字符串(比方说,从“aaaa”到“aaab”等),而不需要生成所有以前的组合,所以它相当快,并且不限于给定的最大字符串长度。
public class StringInc {
public static void main(String[] args) {
System.out.println(next("aaa")); // Prints aab
System.out.println(next("abcdzz")); // Prints abceaa
System.out.println(next("zzz")); // Prints aaaa
}
public static String next(String s) {
int length = s.length();
char c = s.charAt(length - 1);
if(c == 'z')
return length > 1 ? next(s.substring(0, length - 1)) + 'a' : "aa";
return s.substring(0, length - 1) + ++c;
}
}
答案 2 :(得分:4)
增加最后一个字符,如果它达到Z,则将其重置为A并移至前一个字符。重复,直到找到一个不是Z的字符。因为字符串是不可变的,我建议使用一个字符数组来避免分配很多很多新对象。
public static void incrementString(char[] str)
{
for(int pos = str.length - 1; pos >= 0; pos--)
{
if(Character.toUpperCase(str[pos]) != 'Z')
{
str[pos]++;
break;
}
else
str[pos] = 'a';
}
}
答案 3 :(得分:1)
你可以使用大整数的toString(radix)方法,如:
import java.math.BigInteger;
public class Strings {
Strings(final int digits,final int radix) {
this(digits,radix,BigInteger.ZERO);
}
Strings(final int digits,final int radix,final BigInteger number) {
this.digits=digits;
this.radix=radix;
this.number=number;
}
void addOne() {
number=number.add(BigInteger.ONE);
}
public String toString() {
String s=number.toString(radix);
while(s.length()<digits)
s='0'+s;
return s;
}
public char convert(final char c) {
if('0'<=c&&c<='9')
return (char)('a'+(c-'0'));
else if('a'<=c&&c<='p')
return (char)(c+10);
else throw new RuntimeException("more logic required for radix: "+radix);
}
public char convertInverse(final char c) {
if('a'<=c&&c<='j')
return (char)('0'+(c-'a'));
else if('k'<=c&&c<='z')
return (char)(c-10);
else throw new RuntimeException("more logic required for radix: "+radix);
}
void testFix() {
for(int i=0;i<radix;i++)
if(convert(convertInverse((char)('a'+i)))!='a'+i)
throw new RuntimeException("testFix fails for "+i);
}
public String toMyString() {
String s=toString(),t="";
for(int i=0;i<s.length();i++)
t+=convert(s.charAt(i));
return t;
}
public static void main(String[] arguments) {
Strings strings=new Strings(8,26);
strings.testFix();
System.out.println(strings.number.toString()+' '+strings+' '+strings.toMyString());
for(int i=0;i<Math.pow(strings.radix,3);i++)
try {
strings.addOne();
if(Math.abs(i-i/strings.radix*strings.radix)<2)
System.out.println(strings.number.toString()+' '+strings+' '+strings.toMyString());
} catch(Exception e) {
System.out.println(""+i+' '+strings+" failed!");
}
}
final int digits,radix;
BigInteger number;
}
答案 4 :(得分:1)
如果您只想要最终结果,我必须同意@ saua的方法,但在您想要每个结果的情况下,这里有一点点变化。
请注意,由于有26 ^ 8(或208827064576)个不同的可能字符串,我怀疑你想要它们。也就是说,我的代码打印出来而不是只在String Builder中存储一个。 (但这并不重要。)
public static void base26(int maxLength) {
buildWord(maxLength, "");
}
public static void buildWord(int remaining, String word)
{
if (remaining == 0)
{
System.out.println(word);
}
else
{
for (char letter = 'A'; letter <= 'Z'; ++letter)
{
buildWord(remaining-1, word + letter);
}
}
}
public static void main(String[] args)
{
base26(8);
}
答案 5 :(得分:0)
我会创建一个字符数组并单独递增字符。字符串在Java中是不可变的,因此每次更改都会在堆上创建一个新的位置,从而导致内存增长和增长。
使用字符数组,你不应该有这个问题......
答案 6 :(得分:0)
有一个包含ascii值的字节数组,并且具有在进行结转时递增最右边数字的循环。
然后使用
创建字符串public String(byte[] bytes, String charsetName)
确保将charset作为US-ASCII或UTF-8传递为明确的。
答案 7 :(得分:0)
仅扩展示例,就实现而言,考虑将其放入类中......每次调用Class的String时,它都会返回下一个值:
public class Permutator {
private int permutation;
private int permutations;
private StringBuilder stringbuilder;
public Permutator(final int LETTERS) {
if (LETTERS < 1) {
throw new IllegalArgumentException("Usage: Permutator( \"1 or Greater Required\" \)");
}
this.permutation = 0;
// MAGIC NUMBER : 26 = Number of Letters in the English Alphabet
this.permutations = (int) Math.pow(26, LETTERS);
this.stringbuilder = new StringBuilder();
for (int i = 0; i < LETTERS; ++i) {
this.stringbuilder.append('a');
}
}
public String getCount() {
return String.format("Permutation: %s of %s Permutations.", this.permutation, this.permutations);
}
public int getPermutation() {
return this.permutation;
}
public int getPermutations() {
return this.permutations;
}
private void permutate() {
// TODO: Implement Utilising one of the Examples Posted.
}
public String toString() {
this.permutate();
return this.stringbuilder.toString();
}
}
答案 8 :(得分:0)
此代码适用于任何大小的字符串。
public static String iterateAlphabetic(String input) {
String output = input.toUpperCase();
char[] array = output.toCharArray();
boolean overflow = true;
for(int itr=array.length-1; itr>=0; itr--) {
if(overflow && array[itr]=='Z') {
array[itr] = 'A';
overflow = true;
continue;
}
if(overflow) {
array[itr] = next(alphabeticUpper,array[itr]);
overflow = false;
continue;
}
break;
}
if(overflow)
output = "A" + new String(array);
else
output = new String(array);
if(output.length() < input.length())
output = StringUtil.padding(output, 'A', input.length());
return output;
}
public static String padding(String input, char pad, int width) {
if (width < 0)
throw new IllegalArgumentException("width must be > 0");
if (width < input.length())
return input;
StringBuilder sb = new StringBuilder();
for(int i = 0;i < (width - input.length()); i++) {
sb.append(pad);
}
sb.append(input);
return sb.toString();
}
答案 9 :(得分:0)
在@cyberz的解决方案的基础上,以下代码是一个如何编写递归调用的示例,该调用可以由支持Tail Recursion的编译器进行优化。
代码是用Groovy编写的,因为它在JVM上运行,其语法非常类似于Java,它的编译器支持尾递归优化
static String next(String input) {
return doNext(input, "")
}
@TailRecursive
@CompileStatic
static String doNext(String input, String result) {
if(!self) {
return result
}
final String last = input[-1]
final String nonLast = self.substring(0, input.size()-1)
if('z' == last) {
return doNext(nonLast, (nonLast ? 'a' : 'aa') + result)
}
return doNext('', nonLast + (((last as Character) + 1) as Character).toString() + result)
}
答案 10 :(得分:0)
由于没有一个答案对我有用,我编写了自己的代码:
/**
* Increases the given String value by one. Examples (with min 'a' and max 'z'): <p>
*
* - "aaa" -> "aab" <br>
* - "aab" -> "aac" <br>
* - "aaz" -> "aba" <br>
* - "zzz" -> "aaaa" <br>
*
* @param s
* @param min lowest char (a zero)
* @param max highest char (e.g. a 9, in a decimal system)
* @return increased String by 1
*/
public static String incString(String s, char min, char max) {
char last = s.charAt(s.length() - 1);
if (++last > max)
return s.length() > 1 ? incString(s.substring(0, s.length()-1), min, max) + min : "" + min + min;
else
return s.substring(0, s.length()-1) + last;
}
答案 11 :(得分:0)
public static String incrementString(String string)
{
if(string.length()==1)
{
if(string.equals("z"))
return "aa";
else if(string.equals("Z"))
return "Aa";
else
return (char)(string.charAt(0)+1)+"";
}
if(string.charAt(string.length()-1)!='z')
{
return string.substring(0, string.length()-1)+(char)(string.charAt(string.length()-1)+1);
}
return incrementString(string.substring(0, string.length()-1))+"a";
}
适用于所有包含字母的标准字符串
答案 12 :(得分:0)
我有使用 for 循环的方法,这很容易理解。基于[答案]:https://stackoverflow.com/a/2338415/9675605 Cyberz 答案。 这也使用 org.apache.commons.lang3.ArrayUtils。在第一个位置插入字母。你可以为它创建你自己的工具。如果有人觉得有帮助。
import org.apache.commons.lang3.ArrayUtils;
public class StringInc {
public static void main(String[] args) {
System.out.println(next("aaa")); // Prints aab
System.out.println(next("abcdzz")); // Prints abceaa
System.out.println(next("zzz")); // Prints aaaa
}
public static String next(String str) {
boolean increment = true;
char[] arr = str.toCharArray();
for (int i = arr.length - 1; i >= 0 && increment; i--) {
char letter = arr[i];
if (letter != 'z') {
letter++;
increment = false;
} else {
letter = 'a';
}
arr[i] = letter;
}
if (increment) {
arr = ArrayUtils.insert(0, arr, 'a');
}
return new String(arr);
}
答案 13 :(得分:-3)
这不是一个“技巧”,但这适用于4字符串。显然,对于更长的字符串来说它会变得更加丑陋,但这个想法是一样的。
char array[] = new char[4];
for (char c0 = 'a'; c0 <= 'z'; c0++) {
array[0] = c0;
for (char c1 = 'a'; c1 <= 'z'; c1++) {
array[1] = c1;
for (char c2 = 'a'; c2 <= 'z'; c2++) {
array[2] = c2;
for (char c3 = 'a'; c3 <= 'z'; c3++) {
array[3] = c3;
String s = new String(array);
System.out.println(s);
}
}
}
}