多字符替换的字符串组合生成:含yield的C#代码转Java实现
嘿,我完全懂你的困扰!C#里的yield关键字确实让生成这种字符替换组合的代码变得特别简洁,但Java偏偏没有这个语法糖。不过别担心,我们可以用递归或者自定义迭代器的方式,完美复刻原C#代码的功能,甚至还能实现类似的延迟加载效果呢!
解决方案
1. 一次性生成所有组合(简单直观版)
这种方式适合车牌长度不长、组合数量不多的场景,直接把所有可能的组合收集到List里,逻辑和原C#递归+yield的思路一致,只是用回溯递归来实现。
首先定义替换规则,然后编写递归方法:
import java.util.*; public class PlateCombinationGenerator { // 定义替换规则:key是原字符,value是所有可替换的字符(包括自身) private static final Map<Character, List<Character>> REPLACEMENT_RULES = new HashMap<>(); static { REPLACEMENT_RULES.put('1', Arrays.asList('1', 'I')); REPLACEMENT_RULES.put('0', Arrays.asList('0', 'O')); REPLACEMENT_RULES.put('2', Arrays.asList('2', 'Z')); // 可以根据需求添加更多替换规则 } // 对外暴露的生成方法 public static List<String> generatePlateCombinations(String originalPlate) { List<String> combinations = new ArrayList<>(); generateCombinationsRecursive(originalPlate, 0, new StringBuilder(), combinations); return combinations; } // 递归回溯生成组合 private static void generateCombinationsRecursive(String plate, int currentIndex, StringBuilder currentCombination, List<String> result) { // 递归终止条件:处理完所有字符,把当前组合加入结果 if (currentIndex == plate.length()) { result.add(currentCombination.toString()); return; } char currentChar = plate.charAt(currentIndex); // 获取当前字符的所有可能选项:有替换规则就用规则,没有就用自身 List<Character> possibleChars = REPLACEMENT_RULES.getOrDefault(currentChar, Collections.singletonList(currentChar)); // 遍历所有可能的替换字符,递归处理下一个位置 for (char replacement : possibleChars) { currentCombination.append(replacement); generateCombinationsRecursive(plate, currentIndex + 1, currentCombination, result); currentCombination.deleteCharAt(currentCombination.length() - 1); // 回溯,移除当前添加的字符 } } // 使用示例 public static void main(String[] args) { String plate = "ABC123"; List<String> allCombos = generatePlateCombinations(plate); for (String combo : allCombos) { System.out.println(combo); } } }
2. 懒加载版本(类似C# IEnumerable的延迟执行)
如果车牌组合数量很大,一次性生成会占用过多内存,我们可以自定义Iterator来实现类似yield的延迟加载效果——每次调用next()才生成下一个组合,避免一次性加载所有数据。
import java.util.*; public class LazyPlateCombinationGenerator { private static final Map<Character, List<Character>> REPLACEMENT_RULES = new HashMap<>(); static { REPLACEMENT_RULES.put('1', Arrays.asList('1', 'I')); REPLACEMENT_RULES.put('0', Arrays.asList('0', 'O')); // 添加其他规则 } public static Iterable<String> generatePlateCombinationsLazy(String originalPlate) { return () -> new Iterator<String>() { // 用栈模拟递归调用栈,每个元素是[当前索引, 当前组合的StringBuilder] private final Deque<Object[]> callStack = new ArrayDeque<>(); private String nextCombination; // 初始化栈,准备第一个组合的生成 { callStack.push(new Object[]{0, new StringBuilder()}); advanceToNextCombination(); } // 预取下一个组合 private void advanceToNextCombination() { nextCombination = null; while (!callStack.isEmpty()) { Object[] frame = callStack.pop(); int index = (int) frame[0]; StringBuilder current = (StringBuilder) frame[1]; if (index == originalPlate.length()) { nextCombination = current.toString(); return; } char currentChar = originalPlate.charAt(index); List<Character> possibleChars = REPLACEMENT_RULES.getOrDefault(currentChar, Collections.singletonList(currentChar)); // 反向入栈,保证组合顺序和递归版本一致 for (int i = possibleChars.size() - 1; i >= 0; i--) { char replacement = possibleChars.get(i); StringBuilder newCurrent = new StringBuilder(current); newCurrent.append(replacement); callStack.push(new Object[]{index + 1, newCurrent}); } } } @Override public boolean hasNext() { return nextCombination != null; } @Override public String next() { if (!hasNext()) { throw new NoSuchElementException(); } String result = nextCombination; advanceToNextCombination(); return result; } }; } // 使用示例 public static void main(String[] args) { String plate = "ABC123"; Iterable<String> lazyCombos = generatePlateCombinationsLazy(plate); for (String combo : lazyCombos) { System.out.println(combo); } } }
这两种方式都能实现原C#代码的功能,你可以根据实际场景选择合适的版本。
内容的提问来源于stack exchange,提问作者RobbiewOnline
相关产品推荐
相关产品推荐

