import java.util.Collections; import java.util.List; import java.util.stream.Collectors; import java.util.stream.IntStream; /** * 方程式实体类。 * 封装了构成一个数学方程式的所有元素(操作数、操作符)。 * 操作数统一使用 String 类型,以支持数字、函数表达式等多种形式。 */ public class Equation { private final List operands; private final List operators; /** * 构造函数。 * * @param operands 操作数列表(可以是数字、函数表达式等) * @param operators 操作符列表 */ public Equation(List operands, List operators) { this.operands = Collections.unmodifiableList(operands); this.operators = Collections.unmodifiableList(operators); } /** * 获取操作数列表的不可变视图。 * * @return 操作数列表 */ public List getOperands() { return operands; } /** * 获取操作符列表的不可变视图。 * * @return 操作符列表 */ public List getOperators() { return operators; } /** * 生成用于展示给用户和保存到文件的标准问题字符串。 * 格式: "操作数1 运算符1 操作数2 = ?" * * @return 格式化的方程式字符串 */ @Override public String toString() { StringBuilder sb = new StringBuilder(); // 使用 IntStream 来优雅地处理操作数和操作符的交替拼接 IntStream.range(0, operators.size()) .forEach(i -> sb.append(operands.get(i)) .append(" ") .append(operators.get(i).getSymbol()) .append(" ")); sb.append(operands.get(operands.size() - 1)); // 追加最后一个操作数 sb.append(" = ?"); return sb.toString(); } /** * 生成用于唯一性校验的“规范化”字符串。 * 对于简单的可交换运算 (如 "3 + 5"),操作数会排序以确保唯一性 ("3 + 5")。 * 对于复杂或不可交换的运算,直接返回原始顺序的字符串。 * * @return 规范化的方程式字符串 */ public String toCanonicalString() { // 简化处理:仅对两个操作数且操作符可交换的情况进行规范化 if (operands.size() == 2 && operators.size() == 1 && operators.get(0).isCommutative()) { List sortedOperands = operands.stream().sorted().collect(Collectors.toList()); return sortedOperands.get(0) + " " + operators.get(0).getSymbol() + " " + sortedOperands.get(1); } // 对于其他所有复杂情况,直接按原样拼接 return toString().replace(" = ?", ""); } }