I want to implement a wavefront-reader in Java. Therefore I've created some classes to extract a Vector3f and Vector2f (I use JOML for these model classes) or a Triangle (my own model class) from a certain line of a wavefront (.obj) file.I only want to read a special wavefront file (not all types) and only some certain lines.I want to read:3-dimensional geometric Vertices defined as v v1 v2 v32-dimensional TextureCoordinates defined as vt vt1 vt23-dimensional Vertex Normals defined as vn vn1 vn2 vn3The corresponding Faces defined as f v1/vt1/vn1 v2/vt2/vn2 v3/vt3/vn3I use:Spring for dependency-injectionAutoValue classes Guava for collections, functions and preconditions Java 8 for lambda expressionsThe Spring Configuration File@Configuration@ComponentScan(de.sorted.chaos.wavefront.reader)@EnableAutoConfigurationpublic class ApplicationConfiguration {}ModelPoint@AutoValuepublic abstract class Point {  public static Point of(final Integer... indices) {    checkArgument(indices.length == 3, invalid number of of indices for a Point);    final List<Integer> indexList = Arrays.asList(indices);    return new AutoValue_Point(indexList);  }  Point() {}  public abstract List<Integer> indices();  public int vertexIndex() {    return indices().get(0);  }  public int textureIndex() {    return indices().get(1);  }  public int normalIndex() {    return indices().get(2);  }}Triangle@AutoValuepublic abstract class Triangle {  public static Triangle of(final Point... points) {    checkArgument(points.length == 3, invalid number of Points for a Triangle);    final List<Point> pointList = Arrays.asList(points);    return new AutoValue_Triangle(pointList);  }  Triangle() {}  public abstract List<Point> points();  public Point point1() {    return points().get(0);  }  public Point point2() {    return points().get(1);  }  public Point point3() {    return points().get(2);  }}Helpers to get the Elements of a file lineRemoveToken@Componentpublic class RemoveToken {  public List<String> from(final List<String> lineElements) {    final int size = lineElements.size();    return lineElements.subList(1, size);  }}ExtractLineElements@Componentpublic class ExtractLineElements {  private static final String DELIMITER =  ;  @Autowired  private RemoveToken removeToken;  public List<String> from(final String line) {    final List<String> lineElements = Arrays.asList(line.split(DELIMITER));    return removeToken.from(lineElements);  }}ExtractIndices@Componentpublic class ExtractIndices {  private static final String DELIMITER = /;  public List<String> from(final String pointIndices) {    return Arrays.asList(pointIndices.split(DELIMITER));  }}Helpers for transforming the dataToFloat@Componentpublic class ToFloat {  public float from(final String text) {    return Float.parseFloat(text);  }}ToInt@Componentpublic class ToInt {  public int from(final String text) {    return Integer.parseInt(text);  }}ToPoint@Componentpublic class ToPoint {  @Autowired  private ExtractIndices extract;  @Autowired  private ToInt toInt;  public Point from(final String pointIndices) {    final List<String> indices = extract.from(pointIndices);    return toPoint().apply(indices);  }  private Function<List<String>, Point> toPoint() {    return input -> {      checkArgument(input.size() == 3, invalid number of arguments for a Point);      final int vertexIndex = toInt.from(input.get(0));      final int textureIndex = toInt.from(input.get(1));      final int normalIndex = toInt.from(input.get(2));      return Point.of(vertexIndex, textureIndex, normalIndex);    };  }}The TransformersCreateVector3f@Componentpublic class CreateVector3f {  @Autowired  private ExtractLineElements extract;  @Autowired  private ToFloat toFloat;  public Vector3f from(final String line) {    final List<String> lineElements = extract.from(line);    return toVector3f().apply(lineElements);  }  private Function<List<String>, Vector3f> toVector3f() {    return input -> {      checkArgument(input.size() == 3, invalid number of arguments for Vector3f);      final float x = toFloat.from(input.get(0));      final float y = toFloat.from(input.get(1));      final float z = toFloat.from(input.get(2));      return new Vector3f(x, y, z);    };  }}CreateVector2f@Componentpublic class CreateVector2f {  @Autowired  private ExtractLineElements extract;  @Autowired  private ToFloat toFloat;  public Vector2f from(final String line) {    final List<String> lineElements = extract.from(line);    return toVector2f().apply(lineElements);  }  private Function<List<String>, Vector2f> toVector2f() {    return input -> {      checkArgument(input.size() == 2, invalid number of arguments for Vector2f);      final float x = toFloat.from(input.get(0));      final float y = toFloat.from(input.get(1));      return new Vector2f(x, y);    };  }}CreateTriangle@Componentpublic class CreateTriangle {  @Autowired  private ExtractLineElements extract;  @Autowired  private ToPoint toPoint;  public Triangle from(final String line) {    final List<String> lineElements = extract.from(line);    return toTriangle().apply(lineElements);  }  private Function<List<String>, Triangle> toTriangle() {    return input -> {      checkArgument(input.size() == 3, invalid number of arguments for a Triangle);      final Point point1 = toPoint.from(input.get(0));      final Point point2 = toPoint.from(input.get(1));      final Point point3 = toPoint.from(input.get(2));      return Triangle.of(point1, point2, point3);    };  }}Has someone some hints for me to write better code? Perhaps something with generics because the CreateStuff classes look nearly the same (but I have no access to Vector2f and Vector3f classes) - same for the Extractor classes to get the lines of the file. They look nearly the same too.If you are interested in part II - look here.
Wavefront-Reader (.obj) in Java - Part 1
java;guava