我不是一个伟大的程序员,我只是一个具有良好习惯的优秀程序员。
/**
* 几何辅助类
*/
public final class GeometryHelper {
/** 常量相关 */
/** 小数位数 */
private static final int DIGIT_SCALE = 8;
/** 放大比例 */
private static final double ZOOM_SCALE = 10000000000L;
/** 几何工厂 */
private static final GeometryFactory GEOMETRY_FACTORY = new GeometryFactory(new PrecisionModel(PrecisionModel.FLOATING));
/**
* 构造方法
*/
private GeometryHelper() {
throw new UnsupportedOperationException();
}
/**
* 划分线串
*
* @param lineString 原始线串
* @param segmentLengthes 分段长度数组
* @return 线串数组
*/
public static LineString[] splitLineString(LineString lineString, double[] segmentLengthes) {
// 检查分段数量
if (Objects.isNull(segmentLengthes) || segmentLengthes.length < 1) {
return new LineString[] {lineString};
}
// 计算总共长度
double totalLength = Arrays.stream(segmentLengthes)
.map(segmentLength -> Math.max(segmentLength, 0.0D))
.sum();
// 计算目标长度
double lineLength = lineString.getLength();
long[] targetLengthes = Arrays.stream(segmentLengthes)
.mapToLong(segmentLength -> getTargetLength(lineLength, totalLength, segmentLength))
.toArray();
// 初始化参数值
int index = 1;
Coordinate[] coordinates = lineString.getCoordinates();
Coordinate coordinate = coordinates[0];
int length = targetLengthes.length;
LineString[] lineStrings = new LineString[length];
// 添加前面N段
for (int i = 0; i < length - 1; i++) {
// 添加线串坐标
long addupLength = 0L;
List<Coordinate> coordinateList = new ArrayList<>();
coordinateList.add(coordinate);
for (; index < coordinates.length; index++) {
// 计算分段长度
long segmentLength = Math.round(coordinate.distance(coordinates[index]) * ZOOM_SCALE);
// 根据长度处理
boolean isBreak = true;
int compareResult = Long.compare(addupLength + segmentLength, targetLengthes[i]);
// 根据长度处理: 未达目标长度
if (compareResult < 0) {
addupLength += segmentLength;
coordinate = coordinates[index];
coordinateList.add(coordinate);
isBreak = false;
}
// 根据长度处理: 超过目标长度
else if (compareResult > 0) {
long deltaLength = targetLengthes[i] - addupLength;
coordinate = buildMiddleCoordinate(coordinate, coordinates[index], segmentLength, deltaLength);
}
// 根据长度处理: 等于目标长度
else {
index++;
coordinate = coordinates[index];
}
// 是否跳出循环
if (isBreak) {
break;
}
}
coordinateList.add(coordinate);
// 设置线串对象
lineStrings[i] = buildLineString(coordinateList);
}
// 添加最后一段
lineStrings[length - 1] = buildLineString(coordinates, index, coordinate);
// 返回线串数组
return lineStrings;
}
/**
* 构建线串
*
* @param coordinates 坐标数组
* @param index 当前序号
* @param coordinate 当前坐标
* @return 线串
*/
private static LineString buildLineString(Coordinate[] coordinates, int index, Coordinate coordinate) {
List<Coordinate> coordinateList = new ArrayList<>();
coordinateList.add(coordinate);
coordinateList.addAll(Arrays.asList(ArrayUtils.subarray(coordinates, index, coordinates.length)));
return buildLineString(coordinateList);
}
/**
* 构建线串
*
* @param coordinateList 坐标列表
* @return 线串
*/
private static LineString buildLineString(List<Coordinate> coordinateList) {
return GEOMETRY_FACTORY.createLineString(coordinateList.toArray(new Coordinate[0]));
}
/**
* 构建中间坐标
*
* @param coordinate1 坐标1
* @param coordinate2 坐标2
* @param segmentLength 分段长度
* @param deltaLength 增量长度
* @return 中间坐标
*/
private static Coordinate buildMiddleCoordinate(Coordinate coordinate1, Coordinate coordinate2,
long segmentLength, long deltaLength) {
double deltaScale = deltaLength * 1.0D / segmentLength;
double middleX = round(coordinate1.x + (coordinate2.x - coordinate1.x) * deltaScale, DIGIT_SCALE);
double middleY = round(coordinate1.y + (coordinate2.y - coordinate1.y) * deltaScale, DIGIT_SCALE);
return new Coordinate(middleX, middleY);
}
/**
* 获取目标长度
*
* @param lineLength 线路长度
* @param totalLength 总共长度
* @param segmentLength 段长度
* @return 目标长度
*/
private static long getTargetLength(double lineLength, double totalLength, double segmentLength) {
return Math.round(Math.max(segmentLength, 0.0D) * ZOOM_SCALE * lineLength / totalLength);
}
/**
* 四舍五入
*
* @param value 双精度浮点值
* @param scale 保留小数位数
* @return 四舍五入值
*/
private static double round(double value, int scale) {
return BigDecimal.valueOf(value).setScale(scale, BigDecimal.ROUND_HALF_UP).doubleValue();
}
}
- 创建一个新方法,并根据这个方法的意图来命名;
- 将待提炼的代码段从原方法中拷贝到新方法中;
- 检查提炼的代码段,把缺少的变量添加到方法的参数中;
- 如果部分参数成对出现,可以把这些参数合并为一个参数;
- 如果方法需要有返回值,确定返回值的类型,并在合适的位置返回;
- 在原方法中,删除被提炼的代码段,替换为新方法的调用。
/**
* 几何辅助类
*/
public final class GeometryHelper {
/** 原有静态常量 */
......
/**
* 划分线串
*
* @param lineString 原始线串
* @param segmentLengthes 分段长度数组
* @return 线串数组
*/
public static LineString[] splitLineString(LineString lineString, double[] segmentLengthes) {
// 原有计算逻辑
......
// 初始化参数值
int index = 1;
Coordinate[] coordinates = lineString.getCoordinates();
Coordinate coordinate = coordinates[0];
int length = targetLengthes.length;
LineString[] lineStrings = new LineString[length];
// 添加前面N段
for (int i = 0; i < length - 1; i++) {
lineStrings[i] = combineLineString(coordinates, index, coordinate, targetLengthes[i]);
}
// 添加最后一段
lineStrings[length - 1] = buildLineString(coordinates, index, coordinate);
// 返回线串数组
return lineStrings;
}
/**
* 组装线串
*
* @param coordinates 坐标数组
* @param index 当前序号
* @param coordinate 当前坐标
* @param targetLength 目标长度
* @return 线串
*/
private static LineString combineLineString(Coordinate[] coordinates, int index, Coordinate coordinate, long targetLength) {
// 添加线串坐标
long addupLength = 0L;
List<Coordinate> coordinateList = new ArrayList<>();
coordinateList.add(coordinate);
for (; index < coordinates.length; index++) {
// 计算分段长度
long segmentLength = Math.round(coordinate.distance(coordinates[index]) * ZOOM_SCALE);
// 根据长度处理
boolean isBreak = true;
int compareResult = Long.compare(addupLength + segmentLength, targetLength);
// 根据长度处理: 未达目标长度
if (compareResult < 0) {
addupLength += segmentLength;
coordinate = coordinates[index];
coordinateList.add(coordinate);
isBreak = false;
}
// 根据长度处理: 超过目标长度
else if (compareResult > 0) {
long deltaLength = targetLength - addupLength;
coordinate = buildMiddleCoordinate(coordinate, coordinates[index], segmentLength, deltaLength);
}
// 根据长度处理: 等于目标长度
else {
index++;
coordinate = coordinates[index];
}
// 是否跳出循环
if (isBreak) {
break;
}
}
coordinateList.add(coordinate);
// 返回线串对象
return buildLineString(coordinateList);
}
/** 原有静态方法 */
......
}
When you’re passing primitives into a method,you get a distinct copy of the primitive. When you’re passing a reference into a method, you get a copy of the reference. 当您将基本类型传递到方法中时,您将得到该基本类型的副本。当您将对象引用传递到方法中时,您将得到该对象引用的副本。
/**
* 几何辅助类
*/
public final class GeometryHelper {
/** 原有静态常量 */
......
/**
* 划分线串
*
* @param lineString 原始线串
* @param segmentLengthes 分段长度数组
* @return 线串数组
*/
public static LineString[] splitLineString(LineString lineString, double[] segmentLengthes) {
// 原有计算逻辑
......
// 初始化参数值
Coordinate[] coordinates = lineString.getCoordinates();
InoutParameter inoutParameter = new InoutParameter(1, coordinates[0]);
int length = targetLengthes.length;
LineString[] lineStrings = new LineString[length];
// 添加前面N段
for (int i = 0; i < length - 1; i++) {
lineStrings[i] = combineLineString(coordinates, inoutParameter, targetLengthes[i]);
}
// 添加最后一段
lineStrings[length - 1] = buildLineString(coordinates, inoutParameter.getIndex(), inoutParameter.getCoordinate());
// 返回线串数组
return lineStrings;
}
/**
* 组装线串
*
* @param coordinates 坐标数组
* @param inoutParameter 输入输出参数
* @param targetLength 目标长度
* @return 线串
*/
private static LineString combineLineString(Coordinate[] coordinates, InoutParameter inoutParameter, long targetLength) {
// 获取输入参数
int index = inoutParameter.getIndex();
Coordinate coordinate = inoutParameter.getCoordinate();
// 添加线串坐标
......
// 设置输出参数
inoutParameter.setIndex(index);
inoutParameter.setCoordinate(coordinate);
// 返回线串对象
return buildLineString(coordinateList);
}
/** 原有静态方法 */
......
/**
* 输入输出参数类
*/
@Getter
@Setter
@ToString
@NoArgsConstructor
@AllArgsConstructor
private static class InoutParameter {
/** 当前序号 */
private int index;
/** 当前坐标 */
private Coordinate coordinate;
}
}
/**
* 几何辅助类
*/
public final class GeometryHelper {
/** 原有静态常量 */
......
/**
* 划分线串
*
* @param lineString 原始线串
* @param segmentLengthes 分段长度数组
* @return 线串数组
*/
public static LineString[] splitLineString(LineString lineString, double[] segmentLengthes) {
// 原有计算逻辑
......
// 初始化参数值
int[] indexHolder = new int[] {1};
Coordinate[] coordinates = lineString.getCoordinates();
Coordinate[] coordinateHolder = new Coordinate[] {coordinates[0]};
int length = targetLengthes.length;
LineString[] lineStrings = new LineString[length];
// 添加前面N段
for (int i = 0; i < length - 1; i++) {
lineStrings[i] = combineLineString(coordinates, indexHolder, coordinateHolder, targetLengthes[i]);
}
// 添加最后一段
lineStrings[length - 1] = buildLineString(coordinates, indexHolder[0], coordinateHolder[0]);
// 返回线串数组
return lineStrings;
}
/**
* 组装线串
*
* @param coordinates 坐标数组
* @param indexHolder 序号支撑
* @param coordinateHolder 坐标支撑
* @param targetLength 目标长度
* @return 线串
*/
private static LineString combineLineString(Coordinate[] coordinates, int[] indexHolder, Coordinate[] coordinateHolder, long targetLength) {
// 获取支撑取值
int index = indexHolder[0];
Coordinate coordinate = coordinateHolder[0];
// 添加线串坐标
......
// 设置支撑取值
indexHolder[0] = index;
coordinateHolder[0] = coordinate;
// 返回线串对象
return buildLineString(coordinateList);
}
/** 原有静态方法 */
......
}
- Apache的commons-lang3提供的元组类:
- Pair<L, R>:MutablePair<L, R>,ImmutablePair<L, R>
- Triple<L, M, R>:MutableTriple<L, M, R>、ImmutableTriple<L, M, R>
- JavaTuples提供的元组类:
- Unit<A>
- Pair<A,B>,KeyValue<A,B>
- Triplet<A,B,C>
- Quartet<A,B,C,D>
- Quintet<A,B,C,D,E>
- Sextet<A,B,C,D,E,F>
- Septet<A,B,C,D,E,F,G>
- Octet<A,B,C,D,E,F,G,H>
- Ennead<A,B,C,D,E,F,G,H,I>
- Decade<A,B,C,D,E,F,G,H,I,J>
/**
* 几何辅助类
*/
public final class GeometryHelper {
/** 原有静态常量 */
......
/**
* 划分线串
*
* @param lineString 原始线串
* @param segmentLengthes 分段长度数组
* @return 线串数组
*/
public static LineString[] splitLineString(LineString lineString, double[] segmentLengthes) {
// 原有计算逻辑
......
// 初始化参数值
Coordinate[] coordinates = lineString.getCoordinates();
MutablePair<Integer, Coordinate> mutablePair = MutablePair.of(1, coordinates[0]);
int length = targetLengthes.length;
LineString[] lineStrings = new LineString[length];
// 添加前面N段
for (int i = 0; i < length - 1; i++) {
lineStrings[i] = combineLineString(coordinates, mutablePair, targetLengthes[i]);
}
// 添加最后一段
lineStrings[length - 1] = buildLineString(coordinates, mutablePair.getLeft(), mutablePair.getRight());
// 返回线串数组
return lineStrings;
}
/**
* 组装线串
*
* @param coordinates 坐标数组
* @param mutablePair 当前配对
* @param targetLength 目标长度
* @return 线串
*/
private static LineString combineLineString(Coordinate[] coordinates, MutablePair<Integer, Coordinate> mutablePair,
long targetLength) {
// 获取配对取值
int index = mutablePair.getLeft();
Coordinate coordinate = mutablePair.getRight();
// 添加线串坐标
......
// 设置配对取值
mutablePair.setLeft(index);
mutablePair.setRight(coordinate);
// 返回线串对象
return buildLineString(coordinateList);
}
/** 原有静态方法 */
......
}
/**
* 几何辅助类
*/
public final class GeometryHelper {
/** 原有静态常量 */
......
/**
* 划分线串
*
* @param lineString 原始线串
* @param segmentLengthes 分段长度数组
* @return 线串数组
*/
public static LineString[] splitLineString(LineString lineString, double[] segmentLengthes) {
// 原有计算逻辑
......
// 初始化参数值
Coordinate[] coordinates = lineString.getCoordinates();
ObjectHolder<Integer> indexHolder = new ObjectHolder<>(1);
ObjectHolder<Coordinate> coordinateHolder = new ObjectHolder<>(coordinates[0]);
int length = targetLengthes.length;
LineString[] lineStrings = new LineString[length];
// 添加前面N段
for (int i = 0; i < length - 1; i++) {
lineStrings[i] = combineLineString(coordinates, indexHolder, coordinateHolder, targetLengthes[i]);
}
// 添加最后一段
lineStrings[length - 1] = buildLineString(coordinates, indexHolder.getValue(), coordinateHolder.getValue());
// 返回线串数组
return lineStrings;
}
/**
* 组装线串
*
* @param coordinates 坐标数组
* @param indexHolder 序号支撑
* @param coordinateHolder 坐标支撑
* @param targetLength 目标长度
* @return 线串
*/
private static LineString combineLineString(Coordinate[] coordinates, ObjectHolder<Integer> indexHolder, ObjectHolder<Coordinate> coordinateHolder, long targetLength) {
// 获取支撑取值
int index = indexHolder.getValue();
Coordinate coordinate = coordinateHolder.getValue();
// 添加线串坐标
......
// 设置支撑取值
indexHolder.setValue(index);
coordinateHolder.setValue(coordinate);
// 返回线串对象
return buildLineString(coordinateList);
}
/** 原有静态方法 */
......
}
/**
* 对象支撑类
*/
@Getter
@Setter
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class ObjectHolder<T> {
/** 对象取值 */
private T value;
}
/**
* 几何辅助类
*/
public final class GeometryHelper {
/** 原有静态常量 */
......
/**
* 划分线串
*
* @param lineString 原始线串
* @param segmentLengthes 分段长度数组
* @return 线串数组
*/
public static LineString[] splitLineString(LineString lineString, double[] segmentLengthes) {
// 原有计算逻辑
......
// 初始化参数值
int index = 1;
Coordinate[] coordinates = lineString.getCoordinates();
Coordinate coordinate = coordinates[0];
int length = targetLengthes.length;
LineString[] lineStrings = new LineString[length];
// 添加前面N段
for (int i = 0; i < length - 1; i++) {
ReturnResult result = combineLineString(coordinates, index, coordinate, targetLengthes[i]);
index = result.getIndex();
coordinate = result.getCoordinate();
lineStrings[i] = result.getLineString();
}
// 添加最后一段
lineStrings[length - 1] = buildLineString(coordinates, index, coordinate);
// 返回线串数组
return lineStrings;
}
/**
* 组装线串
*
* @param coordinates 坐标数组
* @param index 当前序号
* @param coordinate 当前坐标
* @param targetLength 目标长度
* @return 返回值
*/
private static ReturnResult combineLineString(Coordinate[] coordinates, int index, Coordinate coordinate, long targetLength) {
// 添加线串坐标
......
// 返回输出结果
return new ReturnResult(index, coordinate, buildLineString(coordinateList));
}
/** 原有静态方法 */
......
/**
* 返回值类
*/
@Getter
@Setter
@ToString
@NoArgsConstructor
@AllArgsConstructor
private static class ReturnResult {
/** 当前序号 */
private int index;
/** 当前坐标 */
private Coordinate coordinate;
/** 线串对象 */
private LineString lineString;
}
}
/**
* 几何辅助类
*/
public final class GeometryHelper {
/** 原有静态常量 */
......
/**
* 划分线串
*
* @param lineString 原始线串
* @param segmentLengthes 分段长度数组
* @return 线串数组
*/
public static LineString[] splitLineString(LineString lineString, double[] segmentLengthes) {
// 原有计算逻辑
......
// 初始化参数值
int index = 1;
Coordinate[] coordinates = lineString.getCoordinates();
Coordinate coordinate = coordinates[0];
int length = targetLengthes.length;
LineString[] lineStrings = new LineString[length];
// 添加前面N段
for (int i = 0; i < length - 1; i++) {
Triple<Integer, Coordinate, LineString> triple = combineLineString(coordinates, index, coordinate, targetLengthes[i]);
index = triple.getLeft();
coordinate = triple.getMiddle();
lineStrings[i] = triple.getRight();
}
// 添加最后一段
lineStrings[length - 1] = buildLineString(coordinates, index, coordinate);
// 返回线串数组
return lineStrings;
}
/**
* 组装线串
*
* @param coordinates 坐标数组
* @param index 当前序号
* @param coordinate 当前坐标
* @param targetLength 目标长度
* @return 返回值
*/
private static Triple<Integer, Coordinate, LineString> combineLineString(Coordinate[] coordinates, int index, Coordinate coordinate, long targetLength) {
// 添加线串坐标
......
// 返回输出结果
return ImmutableTriple.of(index, coordinate, buildLineString(coordinateList));
}
/** 原有静态方法 */
......
}
/**
* 几何辅助类
*/
public final class GeometryHelper {
/** 属性相关 */
/** 当前序号支撑 */
private static final ThreadLocal<Integer> INDEX_HOLDER = new ThreadLocal<>();
/** 当前坐标支撑 */
private static final ThreadLocal<Coordinate> COORDINATE_HOLDER = new ThreadLocal<>();
/** 原有静态常量 */
......
/**
* 划分线串
*
* @param lineString 原始线串
* @param segmentLengthes 分段长度数组
* @return 线串数组
*/
public static LineString[] splitLineString(LineString lineString, double[] segmentLengthes) {
// 原有计算逻辑
......
// 初始化参数值
INDEX_HOLDER.set(1);
Coordinate[] coordinates = lineString.getCoordinates();
COORDINATE_HOLDER.set(coordinates[0]);
int length = targetLengthes.length;
LineString[] lineStrings = new LineString[length];
// 添加前面N段
for (int i = 0; i < length - 1; i++) {
lineStrings[i] = combineLineString(coordinates, targetLengthes[i]);
}
// 添加最后一段
lineStrings[length - 1] = buildLineString(coordinates, INDEX_HOLDER.get(), COORDINATE_HOLDER.get());
// 清除支撑类
INDEX_HOLDER.remove();
COORDINATE_HOLDER.remove();
// 返回线串数组
return lineStrings;
}
/**
* 组装线串
*
* @param coordinates 坐标数组
* @param targetLength 目标长度
* @return 线串
*/
private static LineString combineLineString(Coordinate[] coordinates, long targetLength) {
// 获取支撑取值
int index = INDEX_HOLDER.get();
Coordinate coordinate = COORDINATE_HOLDER.get();
// 添加线串坐标
......
// 设置支持取值
INDEX_HOLDER.set(index);
COORDINATE_HOLDER.set(coordinate);
// 返回线串对象
return buildLineString(coordinateList);
}
/** 原有静态方法 */
......
}
/**
* 几何辅助类
*/
public final class GeometryHelper {
// 原有构造方法
......
/**
* 划分线串
*
* @param lineString 原始线串
* @param segmentLengthes 分段长度数组
* @return 线串数组
*/
public static LineString[] splitLineString(LineString lineString, double[] segmentLengthes) {
SplitLineStringAlgorithm algorithm = new SplitLineStringAlgorithm();
return algorithm.splitLineString(lineString, segmentLengthes);
}
}
/**
* 划分线串算法类
*/
public class SplitLineStringAlgorithm {
/** 属性相关 */
/** 当前序号 */
private int index;
/** 当前坐标 */
private Coordinate coordinate;
/** 原有静态常量 */
......
/**
* 划分线串
*
* @param lineString 原始线串
* @param segmentLengthes 分段长度数组
* @return 线串数组
*/
public LineString[] splitLineString(LineString lineString, double[] segmentLengthes) {
// 原有计算逻辑
......
// 初始化参数值
index = 1;
Coordinate[] coordinates = lineString.getCoordinates();
coordinate = coordinates[0];
int length = targetLengthes.length;
LineString[] lineStrings = new LineString[length];
// 添加前面N段
for (int i = 0; i < length - 1; i++) {
lineStrings[i] = combineLineString(coordinates, targetLengthes[i]);
}
// 添加最后一段
lineStrings[length - 1] = buildLineString(coordinates, index, coordinate);
// 返回线串数组
return lineStrings;
}
/**
* 组装线串
*
* @param coordinates 坐标数组
* @param targetLength 目标长度
* @return 线串
*/
private LineString combineLineString(Coordinate[] coordinates, long targetLength) {
// 添加线串坐标
......
// 返回线串对象
return buildLineString(coordinateList);
}
/** 原有静态方法 */
......
}
- 各种实现方法有利有弊,应当根据具体的使用场景,来选择最适合的实现方法。
- 根据参数和返回值的类型选择实现方法:输入输出参数尽量使用方法参数实现,返回值尽量使用返回值实现。
- 根据参数和返回值的数量选择实现方法:数量少的尽量使用支撑类和元组类,数量多的尽量使用自定义类。
- 不建议使用一些取巧的实现方法,比如:3.2.利用单值数组实现、5.1.利用线程本地变量实现。
- 不推荐使用对象数组和对象Map,Java是强类型定义语言,不建议使用强制数据类型转化。
- 最适合本文中案例的实现方法是——3.4.利用支撑类实现。
吾生也有涯,而知也无涯。以有涯随无涯,殆已!
转载请注明:XAMPP中文组官网 » java优秀程序员如何实现参数的输入输出?