示例拓展
金额和货币
创建一个表示金额和货币的值对象(AmountVO),在系统中统一处理货币相关的数据,确保精度和一致性。
| import java.math.BigDecimal; |
| import java.util.Currency; |
| |
| |
| |
| |
| |
| |
| public class AmountVO { |
| |
| private final BigDecimal value; |
| private final Currency currency; |
| |
| |
| |
| |
| |
| |
| |
| public AmountVO(BigDecimal value, Currency currency) { |
| if (value.compareTo(BigDecimal.ZERO) < 0) { |
| throw new IllegalArgumentException("Amount value must not be negative."); |
| } |
| this.value = value; |
| this.currency = currency; |
| } |
| |
| |
| |
| |
| |
| |
| public BigDecimal getValue() { |
| return value; |
| } |
| |
| |
| |
| |
| |
| |
| public Currency getCurrency() { |
| return currency; |
| } |
| |
| |
| |
| |
| |
| |
| |
| @Override |
| public boolean equals(Object obj) { |
| if (this == obj) return true; |
| if (obj == null || getClass() != obj.getClass()) return false; |
| AmountVO amountVO = (AmountVO) obj; |
| return value.equals(amountVO.value) && currency.getCurrencyCode().equals(amountVO.currency.getCurrencyCode()); |
| } |
| |
| |
| |
| |
| |
| |
| @Override |
| public int hashCode() { |
| return Objects.hash(value, currency.getCurrencyCode()); |
| } |
| |
| |
| |
| |
| |
| |
| @Override |
| public String toString() { |
| return value + " " + currency.getCurrencyCode(); |
| } |
| } |
| |
为什么金额和货币可以是值对象?
金额和货币作为值对象(Value Object)的原因在于它们符合值对象的核心特征和设计原则,具体体现在以下几个方面:
- 不可变性:金额和货币组合表示的是一个具体的、不变的值,比如“100美元”或“50欧元”。一旦创建,这个组合不应该被改变,这符合值对象通常设计为不可变对象的原则。
- 相等性基于值:两个金额和货币的组合如果数值和货币种类完全相同,就被视为相等,这与值对象的相等性定义一致,即通过其内在状态而非身份(内存地址)来判断是否相等。
- 无唯一标识:与实体对象(Entity)不同,值对象没有唯一的、持久的身份标识。无论在系统中出现多少次“100美元”,它们都是等价的,不需要区分是哪个具体的实例。
- 可共享:由于值对象表示的是不变的值,因此多个对象可以安全地共享同一个值对象实例,这有助于节省内存并简化逻辑,尤其是在表达如商品价格、账户余额等场景时。
- 封装复杂性:将金额和货币封装在一个值对象中,可以隐藏货币转换、格式化等复杂逻辑,对外提供简洁的接口,提高了代码的可读性和可维护性。
- 领域驱动设计(DDD)中的概念匹配:在领域驱动设计中,值对象用来描述没有唯一标识符但具有某种描述性的对象。金额和货币的组合正是对现实世界中经济交易的一种描述,适合用值对象来建模。
综上所述,将金额和货币设计为值对象,能够有效地提升代码的清晰度、一致性和可维护性,同时确保了在处理财务数据时的准确性和安全性。
创建一个表示价格的值对象(PriceVO)是一个很好的方式来封装和管理商品价格相关的数据,确保数据的一致性和精确计算。
| import java.math.BigDecimal; |
| import java.util.Currency; |
| |
| |
| |
| |
| |
| public class PriceVO { |
| |
| private final BigDecimal amount; |
| private final Currency currency; |
| private final BigDecimal taxRate; |
| |
| |
| |
| |
| |
| |
| |
| |
| public PriceVO(BigDecimal amount, Currency currency, BigDecimal taxRate) { |
| if (amount.compareTo(BigDecimal.ZERO) <= 0) { |
| throw new IllegalArgumentException("Price amount must be greater than zero."); |
| } |
| this.amount = amount; |
| this.currency = currency; |
| this.taxRate = taxRate != null ? taxRate : BigDecimal.ZERO; |
| } |
| |
| |
| |
| |
| |
| |
| public BigDecimal getAmount() { |
| return amount; |
| } |
| |
| |
| |
| |
| |
| |
| public Currency getCurrency() { |
| return currency; |
| } |
| |
| |
| |
| |
| |
| |
| public BigDecimal getTaxInclusiveAmount() { |
| if (taxRate.compareTo(BigDecimal.ZERO) > 0) { |
| return amount.multiply(BigDecimal.ONE.add(taxRate)); |
| } |
| return amount; |
| } |
| |
| |
| |
| |
| |
| |
| public BigDecimal getTaxRate() { |
| return taxRate; |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| if (this == o) return true; |
| if (o == null || getClass() != o.getClass()) return false; |
| PriceVO priceVO = (PriceVO) o; |
| return amount.equals(priceVO.amount) && |
| currency.equals(priceVO.currency) && |
| taxRate.equals(priceVO.taxRate); |
| } |
| |
| @Override |
| public int hashCode() { |
| return Objects.hash(amount, currency, taxRate); |
| } |
| |
| @Override |
| public String toString() { |
| return amount + " " + currency.getCurrencyCode() + |
| (taxRate.compareTo(BigDecimal.ZERO) > 0 ? " (Tax: " + taxRate.multiply(new BigDecimal(100)) + "%)" : ""); |
| } |
| } |
| |
创建一个表示工资的值对象(SalaryVO)可以用来封装员工薪资的细节,包括基本工资、奖金、扣款等部分,并支持不同货币类型。
| import java.math.BigDecimal; |
| import java.util.Currency; |
| |
| |
| |
| |
| |
| |
| public class SalaryVO { |
| |
| private final BigDecimal baseSalary; |
| private final BigDecimal bonus; |
| private final BigDecimal deductions; |
| private final Currency currency; |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| public SalaryVO(BigDecimal baseSalary, BigDecimal bonus, BigDecimal deductions, Currency currency) { |
| if (baseSalary.compareTo(BigDecimal.ZERO) <= 0) { |
| throw new IllegalArgumentException("Base salary must be greater than zero."); |
| } |
| this.baseSalary = baseSalary; |
| this.bonus = bonus != null ? bonus : BigDecimal.ZERO; |
| this.deductions = deductions != null ? deductions : BigDecimal.ZERO; |
| this.currency = currency; |
| } |
| |
| |
| |
| |
| |
| |
| public BigDecimal getBaseSalary() { |
| return baseSalary; |
| } |
| |
| |
| |
| |
| |
| |
| public BigDecimal getBonus() { |
| return bonus; |
| } |
| |
| |
| |
| |
| |
| |
| public BigDecimal getDeductions() { |
| return deductions; |
| } |
| |
| |
| |
| |
| |
| |
| public BigDecimal getTotalSalary() { |
| return baseSalary.add(bonus).subtract(deductions); |
| } |
| |
| |
| |
| |
| |
| |
| public Currency getCurrency() { |
| return currency; |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| if (this == o) return true; |
| if (o == null || getClass() != o.getClass()) return false; |
| SalaryVO salaryVO = (SalaryVO) o; |
| return baseSalary.equals(salaryVO.baseSalary) && |
| bonus.equals(salaryVO.bonus) && |
| deductions.equals(salaryVO.deductions) && |
| currency.equals(salaryVO.currency); |
| } |
| |
| @Override |
| public int hashCode() { |
| return Objects.hash(baseSalary, bonus, deductions, currency); |
| } |
| |
| @Override |
| public String toString() { |
| return "Salary{" + |
| "baseSalary=" + baseSalary + |
| ", bonus=" + bonus + |
| ", deductions=" + deductions + |
| ", totalSalary=" + getTotalSalary() + |
| ", currency=" + currency.getCurrencyCode() + |
| '}'; |
| } |
| } |
| |
创建一个费用值对象(ExpenseVO)可以帮助我们统一管理和计算各种费用项,确保数据的准确性和一致性。
| import java.time.LocalDate; |
| import java.math.BigDecimal; |
| import java.util.Currency; |
| |
| |
| |
| |
| |
| |
| |
| public class ExpenseVO { |
| |
| private final String title; |
| private final BigDecimal amount; |
| private final Currency currency; |
| private final LocalDate date; |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| public ExpenseVO(String title, BigDecimal amount, Currency currency, LocalDate date) { |
| if (title == null || title.isEmpty()) { |
| throw new IllegalArgumentException("Expense title cannot be null or empty."); |
| } |
| if (amount.compareTo(BigDecimal.ZERO) <= 0) { |
| throw new IllegalArgumentException("Expense amount must be greater than zero."); |
| } |
| if (currency == null) { |
| throw new IllegalArgumentException("Currency cannot be null."); |
| } |
| this.title = title; |
| this.amount = amount; |
| this.currency = currency; |
| this.date = date != null ? date : LocalDate.now(); |
| } |
| |
| |
| |
| |
| |
| |
| public String getTitle() { |
| return title; |
| } |
| |
| |
| |
| |
| |
| |
| public BigDecimal getAmount() { |
| return amount; |
| } |
| |
| |
| |
| |
| |
| |
| public Currency getCurrency() { |
| return currency; |
| } |
| |
| |
| |
| |
| |
| |
| public LocalDate getDate() { |
| return date; |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| if (this == o) return true; |
| if (o == null || getClass() != o.getClass()) return false; |
| ExpenseVO expenseVO = (ExpenseVO) o; |
| return title.equals(expenseVO.title) && |
| amount.equals(expenseVO.amount) && |
| currency.equals(expenseVO.currency) && |
| date.equals(expenseVO.date); |
| } |
| |
| @Override |
| public int hashCode() { |
| return Objects.hash(title, amount, currency, date); |
| } |
| |
| @Override |
| public String toString() { |
| return "Expense{" + |
| "title='" + title + '\'' + |
| ", amount=" + amount + |
| ", currency=" + currency.getCurrencyCode() + |
| ", date=" + date + |
| '}'; |
| } |
| } |
| |
度量数据
创建一个重量值对象(WeightVO)可以用来封装和处理重量相关的数据,确保在系统中重量的表示和计算具有一致性和准确性
| |
| |
| |
| |
| |
| |
| |
| public class WeightVO { |
| |
| private final BigDecimal value; |
| private final String unit; |
| |
| |
| |
| |
| |
| |
| |
| public WeightVO(BigDecimal value, String unit) { |
| if (value.compareTo(BigDecimal.ZERO) < 0) { |
| throw new IllegalArgumentException("Weight value must be non-negative."); |
| } |
| if (unit == null || unit.trim().isEmpty()) { |
| throw new IllegalArgumentException("Weight unit cannot be null or empty."); |
| } |
| this.value = value; |
| this.unit = unit.trim().toLowerCase(); |
| } |
| |
| |
| |
| |
| |
| |
| public BigDecimal getValue() { |
| return value; |
| } |
| |
| |
| |
| |
| |
| |
| public String getUnit() { |
| return unit; |
| } |
| |
| |
| |
| |
| |
| |
| |
| @Override |
| public boolean equals(Object obj) { |
| if (this == obj) return true; |
| if (obj == null || getClass() != obj.getClass()) return false; |
| WeightVO weightVO = (WeightVO) obj; |
| return value.compareTo(weightVO.value) == 0; |
| } |
| |
| @Override |
| public int hashCode() { |
| return Objects.hash(value); |
| } |
| |
| |
| |
| |
| |
| |
| @Override |
| public String toString() { |
| return value + " " + unit; |
| } |
| } |
| |
创建一个长度值对象(LengthVO)旨在封装长度数据及其单位,确保在处理尺寸和距离时的精确性和一致性。
| import java.math.BigDecimal; |
| |
| |
| |
| |
| |
| |
| |
| |
| public class LengthVO { |
| |
| private final BigDecimal value; |
| private final String unit; |
| |
| |
| |
| |
| |
| |
| |
| public LengthVO(BigDecimal value, String unit) { |
| if (value.compareTo(BigDecimal.ZERO) < 0) { |
| throw new IllegalArgumentException("Length value must be non-negative."); |
| } |
| if (unit == null || unit.trim().isEmpty()) { |
| throw new IllegalArgumentException("Length unit cannot be null or empty."); |
| } |
| this.value = value; |
| this.unit = unit.trim().toLowerCase(); |
| } |
| |
| |
| |
| |
| |
| |
| public BigDecimal getValue() { |
| return value; |
| } |
| |
| |
| |
| |
| |
| |
| public String getUnit() { |
| return unit; |
| } |
| |
| |
| |
| |
| |
| |
| |
| @Override |
| public boolean equals(Object obj) { |
| if (this == obj) return true; |
| if (obj == null || getClass() != obj.getClass()) return false; |
| LengthVO lengthVO = (LengthVO) obj; |
| return value.compareTo(lengthVO.value) == 0; |
| } |
| |
| @Override |
| public int hashCode() { |
| return Objects.hash(value); |
| } |
| |
| |
| |
| |
| |
| |
| @Override |
| public String toString() { |
| return value + " " + unit; |
| } |
| } |
| |
创建一个体积值对象(VolumeVO)用于封装和处理体积相关的数据,确保在系统中体积的表示和计算既精确又一致
| import java.math.BigDecimal; |
| |
| |
| |
| |
| |
| |
| |
| |
| public class VolumeVO { |
| |
| private final BigDecimal value; |
| private final String unit; |
| |
| |
| |
| |
| |
| |
| |
| public VolumeVO(BigDecimal value, String unit) { |
| if (value.compareTo(BigDecimal.ZERO) < 0) { |
| throw new IllegalArgumentException("Volume value must be non-negative."); |
| } |
| if (unit == null || unit.trim().isEmpty()) { |
| throw new IllegalArgumentException("Volume unit cannot be null or empty."); |
| } |
| this.value = value; |
| this.unit = unit.trim().toLowerCase(); |
| } |
| |
| |
| |
| |
| |
| |
| public BigDecimal getValue() { |
| return value; |
| } |
| |
| |
| |
| |
| |
| |
| public String getUnit() { |
| return unit; |
| } |
| |
| |
| |
| |
| |
| |
| |
| @Override |
| public boolean equals(Object obj) { |
| if (this == obj) return true; |
| if (obj == null || getClass() != obj.getClass()) return false; |
| VolumeVO volumeVO = (VolumeVO) obj; |
| return value.compareTo(volumeVO.value) == 0; |
| } |
| |
| @Override |
| public int hashCode() { |
| return Objects.hash(value); |
| } |
| |
| |
| |
| |
| |
| |
| @Override |
| public String toString() { |
| return value + " " + unit; |
| } |
| } |
| |
范围或区间
创建一个日期范围值对象(DateRangeVO)可以用来表示起始日期和结束日期之间的一个时间区间,这对于处理时间段查询、事件安排等场景非常有用。
| import java.time.LocalDate; |
| |
| |
| |
| |
| |
| |
| public class DateRangeVO { |
| |
| private final LocalDate startDate; |
| private final LocalDate endDate; |
| |
| |
| |
| |
| |
| |
| |
| public DateRangeVO(LocalDate startDate, LocalDate endDate) { |
| if (startDate.isAfter(endDate)) { |
| throw new IllegalArgumentException("Start date must be on or before end date."); |
| } |
| this.startDate = startDate; |
| this.endDate = endDate; |
| } |
| |
| |
| |
| |
| |
| |
| public LocalDate getStartDate() { |
| return startDate; |
| } |
| |
| |
| |
| |
| |
| |
| public LocalDate getEndDate() { |
| return endDate; |
| } |
| |
| |
| |
| |
| |
| |
| |
| public boolean contains(LocalDate date) { |
| return !date.isBefore(startDate) && !date.isAfter(endDate); |
| } |
| |
| |
| |
| |
| |
| |
| public long durationDays() { |
| return ChronoUnit.DAYS.between(startDate, endDate) + 1; |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| if (this == obj) return true; |
| if (obj == null || getClass() != obj.getClass()) return false; |
| DateRangeVO that = (DateRangeVO) obj; |
| return startDate.equals(that.startDate) && endDate.equals(that.endDate); |
| } |
| |
| @Override |
| public int hashCode() { |
| return Objects.hash(startDate, endDate); |
| } |
| |
| |
| |
| |
| |
| |
| @Override |
| public String toString() { |
| return startDate + " to " + endDate; |
| } |
| } |
| |
创建一个温度区间值对象(TemperatureRangeVO)可以用来表示一个最低温度到最高温度之间的区间,这对于气象预报、工业控制等领域非常有用。
| import java.math.BigDecimal; |
| |
| |
| |
| |
| |
| |
| public class TemperatureRangeVO { |
| |
| private final BigDecimal minValue; |
| private final BigDecimal maxValue; |
| private final String unit; |
| |
| |
| |
| |
| |
| |
| |
| |
| public TemperatureRangeVO(BigDecimal minValue, BigDecimal maxValue, String unit) { |
| if (minValue.compareTo(maxValue) > 0) { |
| throw new IllegalArgumentException("Minimum temperature must be less than or equal to maximum temperature."); |
| } |
| if (unit == null || unit.trim().isEmpty()) { |
| throw new IllegalArgumentException("Temperature unit cannot be null or empty."); |
| } |
| this.minValue = minValue; |
| this.maxValue = maxValue; |
| this.unit = unit.trim().toUpperCase(); |
| } |
| |
| |
| |
| |
| |
| |
| public BigDecimal getMinValue() { |
| return minValue; |
| } |
| |
| |
| |
| |
| |
| |
| public BigDecimal getMaxValue() { |
| return maxValue; |
| } |
| |
| |
| |
| |
| |
| |
| public String getUnit() { |
| return unit; |
| } |
| |
| |
| |
| |
| |
| |
| |
| public boolean contains(BigDecimal temp) { |
| return temp.compareTo(minValue) >= 0 && temp.compareTo(maxValue) <= 0; |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| if (this == obj) return true; |
| if (obj == null || getClass() != obj.getClass()) return false; |
| TemperatureRangeVO that = (TemperatureRangeVO) obj; |
| return minValue.compareTo(that.minValue) == 0 && maxValue.compareTo(that.maxValue) == 0 && unit.equals(that.unit); |
| } |
| |
| @Override |
| public int hashCode() { |
| return Objects.hash(minValue, maxValue, unit); |
| } |
| |
| |
| |
| |
| |
| |
| @Override |
| public String toString() { |
| return minValue + "°" + unit + " to " + maxValue + "°" + unit; |
| } |
| } |
| |
数学模型
创建一个坐标值对象(CoordinateVO)可以用来封装二维空间中的位置信息,通常包括经度(longitude)和纬度(latitude)。
| |
| |
| |
| |
| |
| |
| |
| |
| |
| public class CoordinateVO { |
| |
| private final double longitude; |
| private final double latitude; |
| |
| |
| |
| |
| |
| |
| |
| public CoordinateVO(double longitude, double latitude) { |
| if (longitude < -180 || longitude > 180) { |
| throw new IllegalArgumentException("Longitude must be between -180 and 180."); |
| } |
| if (latitude < -90 || latitude > 90) { |
| throw new IllegalArgumentException("Latitude must be between -90 and 90."); |
| } |
| this.longitude = longitude; |
| this.latitude = latitude; |
| } |
| |
| |
| |
| |
| |
| |
| public double getLongitude() { |
| return longitude; |
| } |
| |
| |
| |
| |
| |
| |
| public double getLatitude() { |
| return latitude; |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| if (this == obj) return true; |
| if (obj == null || getClass() != obj.getClass()) return false; |
| CoordinateVO coordinateVO = (CoordinateVO) obj; |
| return Double.compare(coordinateVO.longitude, longitude) == 0 && Double.compare(coordinateVO.latitude, latitude) == 0; |
| } |
| |
| @Override |
| public int hashCode() { |
| return Objects.hash(longitude, latitude); |
| } |
| |
| |
| |
| |
| |
| |
| @Override |
| public String toString() { |
| return "(" + longitude + ", " + latitude + ")"; |
| } |
| } |
| |
创建一个向量值对象(VectorVO)可以用来表示具有大小(magnitude)和方向的量,通常在物理、工程和计算机图形学等领域中使用。这里我们以二维向量为例,它包含x分量和y分量。
| |
| |
| |
| |
| |
| |
| |
| |
| public class VectorVO { |
| |
| private final double xComponent; |
| private final double yComponent; |
| |
| |
| |
| |
| |
| |
| |
| public VectorVO(double xComponent, double yComponent) { |
| this.xComponent = xComponent; |
| this.yComponent = yComponent; |
| } |
| |
| |
| |
| |
| |
| |
| public double getXComponent() { |
| return xComponent; |
| } |
| |
| |
| |
| |
| |
| |
| public double getYComponent() { |
| return yComponent; |
| } |
| |
| |
| |
| |
| |
| |
| public double magnitude() { |
| return Math.sqrt(xComponent * xComponent + yComponent * yComponent); |
| } |
| |
| |
| |
| |
| |
| |
| |
| public VectorVO add(VectorVO other) { |
| return new VectorVO(this.xComponent + other.xComponent, this.yComponent + other.yComponent); |
| } |
| |
| |
| |
| |
| |
| |
| |
| public VectorVO subtract(VectorVO other) { |
| return new VectorVO(this.xComponent - other.xComponent, this.yComponent - other.yComponent); |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| if (this == obj) return true; |
| if (obj == null || getClass() != obj.getClass()) return false; |
| VectorVO vectorVO = (VectorVO) obj; |
| return Double.compare(vectorVO.xComponent, xComponent) == 0 && Double.compare(vectorVO.yComponent, yComponent) == 0; |
| } |
| |
| @Override |
| public int hashCode() { |
| return Objects.hash(xComponent, yComponent); |
| } |
| |
| |
| |
| |
| |
| |
| @Override |
| public String toString() { |
| return "<" + xComponent + ", " + yComponent + ">"; |
| } |
| } |
| |
创建线性回归模型(LinearRegressionModelVO)值对象
线性回归是一种统计方法,用于预测一个连续响应变量与一个或多个预测变量之间的关系。这个值对象将包括模型参数(斜率和截距)、相关系数(如R²)、训练数据集的摘要统计信息等。
| import java.util.List; |
| |
| |
| |
| |
| |
| |
| |
| public class LinearRegressionModelVO { |
| |
| private final double slope; |
| private final double intercept; |
| private final double rSquared; |
| private final List<Double> featureMeans; |
| private final List<Double> featureStdDevs; |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| public LinearRegressionModelVO(double slope, double intercept, double rSquared, |
| List<Double> featureMeans, List<Double> featureStdDevs) { |
| if (featureMeans == null || featureStdDevs == null || featureMeans.size() != featureStdDevs.size()) { |
| throw new IllegalArgumentException("Feature means and standard deviations lists must not be null and of the same size."); |
| } |
| this.slope = slope; |
| this.intercept = intercept; |
| this.rSquared = rSquared; |
| this.featureMeans = featureMeans; |
| this.featureStdDevs = featureStdDevs; |
| } |
| |
| |
| |
| |
| |
| |
| public double getSlope() { |
| return slope; |
| } |
| |
| |
| |
| |
| |
| |
| public double getIntercept() { |
| return intercept; |
| } |
| |
| |
| |
| |
| |
| |
| public double getRSquared() { |
| return rSquared; |
| } |
| |
| |
| |
| |
| |
| |
| public List<Double> getFeatureMeans() { |
| return featureMeans; |
| } |
| |
| |
| |
| |
| |
| |
| public List<Double> getFeatureStdDevs() { |
| return featureStdDevs; |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| if (this == obj) return true; |
| if (obj == null || getClass() != obj.getClass()) return false; |
| LinearRegressionModelVO that = (LinearRegressionModelVO) obj; |
| return Double.compare(that.slope, slope) == 0 && |
| Double.compare(that.intercept, intercept) == 0 && |
| Double.compare(that.rSquared, rSquared) == 0 && |
| featureMeans.equals(that.featureMeans) && |
| featureStdDevs.equals(that.featureStdDevs); |
| } |
| |
| @Override |
| public int hashCode() { |
| return Objects.hash(slope, intercept, rSquared, featureMeans, featureStdDevs); |
| } |
| |
| |
| |
| |
| |
| |
| @Override |
| public String toString() { |
| return "Slope: " + slope + ", Intercept: " + intercept + ", R²: " + rSquared; |
| } |
| } |
| |
创建一个多项式回归模型值对象(PolynomialRegressionModelVO)
多项式回归是线性回归的一种扩展,允许因变量和一个或多个自变量之间的关系以多项式形式建模。这个值对象会包含多项式系数、阶次、训练数据的性能指标等信息。
| import java.util.List; |
| |
| |
| |
| |
| |
| |
| public class PolynomialRegressionModelVO { |
| |
| private final int degree; |
| private final List<Double> coefficients; |
| private final double rSquared; |
| private final List<Double> featureMeans; |
| private final List<Double> featureStdDevs; |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| public PolynomialRegressionModelVO(int degree, List<Double> coefficients, double rSquared, |
| List<Double> featureMeans, List<Double> featureStdDevs) { |
| if (coefficients == null || coefficients.isEmpty() || featureMeans == null || featureStdDevs == null || |
| featureMeans.size() != featureStdDevs.size()) { |
| throw new IllegalArgumentException("Coefficients, feature means, and standard deviations must not be null or incorrectly sized."); |
| } |
| if (degree != coefficients.size() - 1) { |
| throw new IllegalArgumentException("Degree does not match the number of coefficients provided."); |
| } |
| this.degree = degree; |
| this.coefficients = coefficients; |
| this.rSquared = rSquared; |
| this.featureMeans = featureMeans; |
| this.featureStdDevs = featureStdDevs; |
| } |
| |
| |
| |
| |
| |
| |
| public int getDegree() { |
| return degree; |
| } |
| |
| |
| |
| |
| |
| |
| public List<Double> getCoefficients() { |
| return coefficients; |
| } |
| |
| |
| |
| |
| |
| |
| public double getRSquared() { |
| return rSquared; |
| } |
| |
| |
| |
| |
| |
| |
| public List<Double> getFeatureMeans() { |
| return featureMeans; |
| } |
| |
| |
| |
| |
| |
| |
| public List<Double> getFeatureStdDevs() { |
| return featureStdDevs; |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| if (this == obj) return true; |
| if (obj == null || getClass() != obj.getClass()) return false; |
| PolynomialRegressionModelVO that = (PolynomialRegressionModelVO) obj; |
| return degree == that.degree && |
| coefficients.equals(that.coefficients) && |
| Double.compare(that.rSquared, rSquared) == 0 && |
| featureMeans.equals(that.featureMeans) && |
| featureStdDevs.equals(that.featureStdDevs); |
| } |
| |
| @Override |
| public int hashCode() { |
| return Objects.hash(degree, coefficients, rSquared, featureMeans, featureStdDevs); |
| } |
| |
| |
| |
| |
| |
| |
| @Override |
| public String toString() { |
| return "Degree: " + degree + ", Coefficients: " + coefficients + ", R²: " + rSquared; |
| } |
| } |
| |
创建一个矩阵值对象(MatrixVO)
用于表示数学中的矩阵。矩阵是线性代数中的基本概念,广泛应用于计算机图形学、机器学习、工程计算等多个领域。这个值对象将能够存储矩阵的维度信息以及矩阵中的元素值。
| import java.util.ArrayList; |
| import java.util.List; |
| |
| |
| |
| |
| |
| |
| |
| public class MatrixVO { |
| |
| private final int rows; |
| private final int columns; |
| private final List<List<Double>> elements; |
| |
| |
| |
| |
| |
| |
| |
| |
| public MatrixVO(int rows, int columns, List<List<Double>> elements) { |
| if (rows <= 0 || columns <= 0) { |
| throw new IllegalArgumentException("Number of rows and columns must be positive."); |
| } |
| if (elements == null || elements.size() != rows || !elements.stream().allMatch(row -> row != null && row.size() == columns)) { |
| throw new IllegalArgumentException("Elements list does not match the specified dimensions."); |
| } |
| this.rows = rows; |
| this.columns = columns; |
| this.elements = new ArrayList<>(elements); |
| } |
| |
| |
| |
| |
| |
| |
| public int getRows() { |
| return rows; |
| } |
| |
| |
| |
| |
| |
| |
| public int getColumns() { |
| return columns; |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| public double getElementAt(int row, int column) { |
| return elements.get(row).get(column); |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| public void setElementAt(int row, int column, double value) { |
| elements.get(row).set(column, value); |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| if (this == obj) return true; |
| if (obj == null || getClass() != obj.getClass()) return false; |
| MatrixVO matrixVO = (MatrixVO) obj; |
| return rows == matrixVO.rows && columns == matrixVO.columns && elements.equals(matrixVO.elements); |
| } |
| |
| @Override |
| public int hashCode() { |
| return Objects.hash(rows, columns, elements); |
| } |
| |
| |
| |
| |
| |
| |
| @Override |
| public String toString() { |
| StringBuilder sb = new StringBuilder("["); |
| for (int i = 0; i < rows; i++) { |
| if (i > 0) sb.append(", "); |
| sb.append("["); |
| for (int j = 0; j < columns; j++) { |
| if (j > 0) sb.append(", "); |
| sb.append(elements.get(i).get(j)); |
| } |
| sb.append("]"); |
| } |
| sb.append("]"); |
| return sb.toString(); |
| } |
| } |
| |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 提示词工程——AI应用必不可少的技术
· 地球OL攻略 —— 某应届生求职总结
· 字符编码:从基础到乱码解决
· SpringCloud带你走进微服务的世界