用映射替换 switch 语句(针对不同的数据类型)
Replace switch statement with a map (for different data-types)
我正在尝试用映射替换以下 switch 语句。
public ObjGeometry geometry(final Iterable<String> lines) throws IllegalArgumentException {
final List<Vector3f> vertices = Lists.newArrayList();
final List<Vector2f> textures = Lists.newArrayList();
final List<Vector3f> normals = Lists.newArrayList();
final List<Face> faces = Lists.newArrayList();
for (final String line : lines) {
final List<String> lineElements = Arrays.asList(line.split(" "));
final String token = lineElements.get(0);
switch (token) {
case VERTEX:
final Vector3f vertex = createVertex(lineElements);
vertices.add(vertex);
break;
case TEXTURE:
final Vector2f texture = createTexture(lineElements);
textures.add(texture);
break;
case NORMAL:
final Vector3f normal = createNormal(lineElements);
normals.add(normal);
break;
case FACES:
final Face face = createFace(lineElements);
faces.add(face);
break;
}
}
return ObjGeometry.from(vertices, textures, normals, faces);
}
方法 #createVertex
、#createTexture
、#createNormal
和 #createFace
将字符串转换为特殊数据类型(Vector2f、Vector3f 或 Face)
我想做的是...构建一个映射 Map<TOKEN, Parser>
,这样我就可以遍历该映射并为特殊标记调用正确的解析器(顺便说一句。TOKEN 是一个类似于 "v"、"vt"、"vn" 或 "f").
我有的是:
- abstract class
ExtractVector3f
with method #vectorFrom(List<String>)
- 可以将 List<String>
转换为 Vector3f
- abstract class
ExtractVector2f
with method #vectorFrom(List<String>)
- 可以将 List<String>
转换为 Vector2f
- abstract class
ExtractFace
with method #faceFrom(List<String>)
- 可以将 List<String>
转换为 Face
一个接口LineParser
public interface LineParser<T> {
T apply(final List<String> lineElements);
}
a class 解析一个顶点
public class ParseVertex extends ExtractVector3f implements LineParser<Vector3f> {
@Override
public Vector3f apply(final List<String> lineElements) {
return vectorFrom(lineElements);
}
}
a class解析正常
public class ParseNormal extends ExtractVector3f implements LineParser<Vector3f> {
@Override
public Vector3f apply(final List<String> lineElements) {
return vectorFrom(lineElements);
}
}
a class 解析纹理
public class ParseTexture extends ExtractVector2f implements LineParser<Vector2f> {
@Override
public Vector2f apply(final List<String> lineElements) {
return vectorFrom(lineElements);
}
}
和一个class来解析一张脸
public class ParseFace extends ExtractFaces implements LineParser<Face> {
@Override
public Face apply(final List<String> lineElements) {
return faceFrom(lineElements);
}
}
下一步是构建地图...类似
Map<String, LineParser> parsers = Maps.newHashMap();
parsers.put("v", new ParseVertex());
parsers.put("vt", new ParseTexture());
parsers.put("vn", new ParseNormal());
parsers.put("f", new ParseFace());
但是现在我遇到麻烦了。此映射中的 LineParser 是原始类型,应避免使用原始类型。
我的问题是:
我如何构建一个地图,其中包含 POJO - return 通过接口定义的方法上的不同数据类型?
实际上我不会这样做。即使地图是个好主意,这样做也会丢失您构建的对象的确切类型。在那之后你打算怎么处理他们?你怎么知道将它们添加到哪个集合?你不能,除非解析器可以访问所有集合以选择正确的集合。这表明解析器应该知道您的主要 class 或此 class.
的方法
我只会使用 lambdas :
Consumer<List<String>> handleTexture = args -> textures.add(parseTexture(args))
Consumer<List<String>> handleVertice = args -> vertices.add(parseVertice(args))
...
Map<String, Consumer<List<String>> handlers = new HashMap<>();
handlers.put("vf", handleTexture);
handlers.put("v", handleVertice);
...
for (final String line : lines) {
final List<String> lineElements = Arrays.asList(line.split(" "));
final String token = lineElements.get(0);
handlers.get(token).accept(lineElements.sublist(1, lineElements.size()));)
}
如果你想用 Java 7 来做它在语法上不太好,但原理是一样的。使用方法 accept
创建一个像 Consumer
这样的接口(如果你想让 class 更适合你的项目,你可以更改所有的名称,比如 Parser
和 parse
, 只需为方法保留相同的签名):
public class Consumer<T> {
public void accept(T t);
}
然后,在您的代码中
Consumer<List<String>> handleTexture = new Consumer<List<String>>() {
@Override
public void accept(List<String> args) {
textures.add(parseTexture(args));
}
}
其余同理!
我正在尝试用映射替换以下 switch 语句。
public ObjGeometry geometry(final Iterable<String> lines) throws IllegalArgumentException {
final List<Vector3f> vertices = Lists.newArrayList();
final List<Vector2f> textures = Lists.newArrayList();
final List<Vector3f> normals = Lists.newArrayList();
final List<Face> faces = Lists.newArrayList();
for (final String line : lines) {
final List<String> lineElements = Arrays.asList(line.split(" "));
final String token = lineElements.get(0);
switch (token) {
case VERTEX:
final Vector3f vertex = createVertex(lineElements);
vertices.add(vertex);
break;
case TEXTURE:
final Vector2f texture = createTexture(lineElements);
textures.add(texture);
break;
case NORMAL:
final Vector3f normal = createNormal(lineElements);
normals.add(normal);
break;
case FACES:
final Face face = createFace(lineElements);
faces.add(face);
break;
}
}
return ObjGeometry.from(vertices, textures, normals, faces);
}
方法 #createVertex
、#createTexture
、#createNormal
和 #createFace
将字符串转换为特殊数据类型(Vector2f、Vector3f 或 Face)
我想做的是...构建一个映射 Map<TOKEN, Parser>
,这样我就可以遍历该映射并为特殊标记调用正确的解析器(顺便说一句。TOKEN 是一个类似于 "v"、"vt"、"vn" 或 "f").
我有的是:
- abstract class
ExtractVector3f
with method#vectorFrom(List<String>)
- 可以将List<String>
转换为Vector3f
- abstract class
ExtractVector2f
with method#vectorFrom(List<String>)
- 可以将List<String>
转换为Vector2f
- abstract class
ExtractFace
with method#faceFrom(List<String>)
- 可以将List<String>
转换为Face
一个接口
LineParser
public interface LineParser<T> { T apply(final List<String> lineElements); }
a class 解析一个顶点
public class ParseVertex extends ExtractVector3f implements LineParser<Vector3f> { @Override public Vector3f apply(final List<String> lineElements) { return vectorFrom(lineElements); } }
a class解析正常
public class ParseNormal extends ExtractVector3f implements LineParser<Vector3f> { @Override public Vector3f apply(final List<String> lineElements) { return vectorFrom(lineElements); } }
a class 解析纹理
public class ParseTexture extends ExtractVector2f implements LineParser<Vector2f> { @Override public Vector2f apply(final List<String> lineElements) { return vectorFrom(lineElements); } }
和一个class来解析一张脸
public class ParseFace extends ExtractFaces implements LineParser<Face> { @Override public Face apply(final List<String> lineElements) { return faceFrom(lineElements); } }
下一步是构建地图...类似
Map<String, LineParser> parsers = Maps.newHashMap();
parsers.put("v", new ParseVertex());
parsers.put("vt", new ParseTexture());
parsers.put("vn", new ParseNormal());
parsers.put("f", new ParseFace());
但是现在我遇到麻烦了。此映射中的 LineParser 是原始类型,应避免使用原始类型。
我的问题是: 我如何构建一个地图,其中包含 POJO - return 通过接口定义的方法上的不同数据类型?
实际上我不会这样做。即使地图是个好主意,这样做也会丢失您构建的对象的确切类型。在那之后你打算怎么处理他们?你怎么知道将它们添加到哪个集合?你不能,除非解析器可以访问所有集合以选择正确的集合。这表明解析器应该知道您的主要 class 或此 class.
的方法我只会使用 lambdas :
Consumer<List<String>> handleTexture = args -> textures.add(parseTexture(args))
Consumer<List<String>> handleVertice = args -> vertices.add(parseVertice(args))
...
Map<String, Consumer<List<String>> handlers = new HashMap<>();
handlers.put("vf", handleTexture);
handlers.put("v", handleVertice);
...
for (final String line : lines) {
final List<String> lineElements = Arrays.asList(line.split(" "));
final String token = lineElements.get(0);
handlers.get(token).accept(lineElements.sublist(1, lineElements.size()));)
}
如果你想用 Java 7 来做它在语法上不太好,但原理是一样的。使用方法 accept
创建一个像 Consumer
这样的接口(如果你想让 class 更适合你的项目,你可以更改所有的名称,比如 Parser
和 parse
, 只需为方法保留相同的签名):
public class Consumer<T> {
public void accept(T t);
}
然后,在您的代码中
Consumer<List<String>> handleTexture = new Consumer<List<String>>() {
@Override
public void accept(List<String> args) {
textures.add(parseTexture(args));
}
}
其余同理!