在我的实现中,我希望该方法具有不同的返回类型。

huangapple go评论74阅读模式
英文:

In my implementation I want to have different return type of the method

问题

我有以下问题。我有以下接口:

public interface Parser {
    public Map<String, List<String>> parse() throws IOException;
}

我有两个实现:

public class RacerInfoParser implements Parser{
    private final Path path;
    
    public RacerInfoParser(Path path) {
        this.path = path;
    }
    
    @Override
    public Map<String, List<String>> parse() throws IOException {
        try (Stream<String> lines = Files.lines(path)){
            
            Map<Object, Object> map = lines.collect(Collectors.toMap(
                string -> string.substring(0,3),
                string -> Arrays.asList(string.substring(4).split("_"))));
            
            Map<String, List<String>> result = new HashMap<>((Map) map);
            return result;
        }
    }
}

public class TimeParser implements Parser {
    private final Path path;
    
    public TimeParser(Path path) {
        this.path = path;
    }
    
    @Override
    public Map<String, List<String>> parse() throws IOException {
        try (Stream<String> lines = Files.lines(path)){
            
            Map<Object, Object> map = lines.collect(Collectors.toMap(
                string -> string.substring(0,3),
                string -> Arrays.asList(string.substring(3).split("_"))));
            Map<String, List<String>> result = new HashMap<>((Map) map);
            return result;
        }
    }
}

我想要做的是更改代码和TimeParser的返回类型,使其返回类型为Map<String, List<LocalTime>>。我已经阅读到为了拥有不同的类型,我需要父类型的子类,但我不知道如何在我的情况下做到这一点。

附:我知道Map<String, List<String>> result = new HashMap<>((Map) map);是不好的代码,但我还不知道如何正确地将Map<Object, Object>转换为Map<String, List<String>>。如果您有任何建议,我将很乐意听取:)。

附加附:我使用这两个实现是因为我相信它们做了相同的事情:解析日志和txt文件中的文本:

public class RacerBuilder {
    public List<Racer> buildRacers() throws URISyntaxException, IOException {
        Parser racerInfoParser = new RacerInfoParser(Paths.get(getClass().getClassLoader()
            .getResource("abbreviations.txt").toURI()));
        Parser startTimeParser = new TimeParser(Paths.get(getClass().getClassLoader()
            .getResource("start.log").toURI()));
        Parser endTimeParser = new TimeParser(Paths.get(getClass().getClassLoader()
            .getResource("end.log").toURI()));
            
        Map<String, List<String>> racerInfoMap = racerInfoParser.parse();
        Map<String, List<String>> startTimeMap = startTimeParser.parse();
        Map<String, List<String>> endTimeMap = endTimeParser.parse();
        
        return racerInfoMap.keySet().stream()
            .map(i -> new Racer(i,
                racerInfoMap.get(i).get(0),
                racerInfoMap.get(i).get(1),
                startTimeMap.get(i).get(1),
                endTimeMap.get(i).get(1),
                endTimeMap.get(i).get(0)))
            .collect(Collectors.toList());
    }
}

Racer类现在有几个字段,全部都是字符串。我希望它有2个LocalTime类型的字段。

英文:

I have the following problem. I have the interface:

public interface Parser {
public Map&lt;String, List&lt;String&gt;&gt; parse() throws IOException;
}

I have two implementations:

public class RacerInfoParser implements Parser{
private final Path path;
public RacerInfoParser(Path path) {
this.path = path;	
}
@Override
public Map &lt;String, List&lt;String&gt;&gt; parse() throws IOException {
try (Stream&lt;String&gt;lines = Files.lines(path)){
Map &lt;Object, Object&gt; map = lines.collect(Collectors.toMap(
string -&gt; string.substring(0,3),
string -&gt; Arrays.asList(string.substring(4).split(&quot;_&quot;))));
Map&lt;String, List&lt;String&gt;&gt; result = new HashMap&lt;&gt;((Map) map);
return result;
}
}
}

and

public class TimeParser implements Parser {
private final Path path;
public TimeParser(Path path) {
this.path = path;	
}
@Override
public Map &lt;String, List&lt;String&gt;&gt; parse() throws IOException {
try (Stream&lt;String&gt;lines = Files.lines(path)){
Map &lt;Object, Object&gt; map = lines.collect(Collectors.toMap(
string -&gt; string.substring(0,3),
string -&gt; Arrays.asList(string.substring(3).split(&quot;_&quot;))));
Map&lt;String, List&lt;String&gt;&gt; result = new HashMap&lt;&gt;((Map) map);
return result;
}
}
}

What I want to do is to change the code and the return type of TimeParser so that it returns the result of type Map&lt;String, List &lt;LocalTime&gt;. I have read that in order to have a different type I need to have a sub-class of the parent type, but I don't understand how to do it in my case.

P.S. I know that Map&lt;String, List&lt;String&gt;&gt; result = new HashMap&lt;&gt;((Map) map); is a bad code, but I don't know yet how to properly convert Map&lt;Object, Object to Map&lt;String, List&lt;String&gt;&gt;. If you have any suggestions I will be glad to listen to them:).

P.S.S. I use these two implementations because I beleive they do the same thing: parse text from log and txt files:

    public class RacerBuilder {
public List&lt;Racer&gt; buildRacers () throws URISyntaxException, IOException {
Parser racerInfoParser = new RacerInfoParser(Paths.get(getClass().getClassLoader()
.getResource(&quot;abbreviations.txt&quot;).toURI()));
Parser startTimeParser = new TimeParser(Paths.get(getClass().getClassLoader()
.getResource(&quot;start.log&quot;).toURI()));
Parser endTimeParser = new TimeParser(Paths.get(getClass().getClassLoader()
.getResource(&quot;end.log&quot;).toURI()));
Map&lt;String, List&lt;String&gt;&gt; racerInfoMap = racerInfoParser.parse();
Map&lt;String, List&lt;String&gt;&gt; startTimeMap = startTimeParser.parse();
Map&lt;String, List&lt;String&gt;&gt; endTimeMap = endTimeParser.parse();
return racerInfoMap.keySet().stream()
.map(i -&gt; new Racer (i,
racerInfoMap.get(i).get(0),
racerInfoMap.get(i).get(1),
startTimeMap.get(i).get(1),
endTimeMap.get(i).get(1),
endTimeMap.get(i).get(0)))
.collect(Collectors.toList());	
}
}

Racer class now has several fields, all of them are Strings. I want it to have 2 fields of type LocalTime.

答案1

得分: 3

接受以下两种情况之一:
Map<String, List<String>>;
或者
Map<String, List<LocalTime>>;
您可以在此情况下使用泛型,您只需要使用:
<T> Map<String, List<T>> parse() throws IOException;
^
此外,您的代码可以是:
return lines.collect(Collectors.toMap(
string -> string.substring(0, 3),
string -> Arrays.asList(string.substring(4).split("_"))));
或者,如果您想要一个 LocalTime 的列表,您可以解析您的字符串并收集如下:
return lines.collect(Collectors.toMap(
string -> string.substring(0, 3),
string -> Arrays.stream(string.substring(4).split("_"))
.map(LocalTime::parse) // 或者您可以使用日期时间格式化程序
.collect(Collectors.toList())
通过使用这种解决方案,您不需要进行类型转换。
英文:

To accept either :

Map&lt;String, List&lt;String&gt;&gt;

or

Map&lt;String, List&lt;LocalTime&gt;&gt;

You can use generic in this case, all you need is to use :

&lt;T&gt; Map&lt;String, List&lt;T&gt;&gt; parse() throws IOException;
^

Also your code can be :

return lines.collect(Collectors.toMap(
string -&gt; string.substring(0, 3),
string -&gt; Arrays.asList(string.substring(4).split(&quot;_&quot;))));

Or if you want a List of LocalTime, you can parse your String and collect as this:

return lines.collect(Collectors.toMap(
string -&gt; string.substring(0, 3),
string -&gt; Arrays.stream(string.substring(4).split(&quot;_&quot;))
.map(LocalTime::parse) // or you can use a Date time formatter
.collect(Collectors.toList())

You don't need to cast with this solution.

答案2

得分: 2

我会将Map<String, List<String>>放在一个新类中,并提供一个getter,让我们称其为MapAsString。将其作为类层次结构的一部分,这样你就会有class MapAsString extends DataMap。接下来,创建一个新类,它是DataMap的子类,或许叫做MapAsLocalTime,其中MapAsLocalTime extends DataMap

额外加分:将你的父类class DataMap定义为抽象类,并提供一个单一的抽象方法,你必须实现这个方法。这个方法使用泛型来返回一个List<String, T>。你可以有一个构造函数,接受一个T(泛型类型),该类型在构造时定义。如果这看起来太难,或许只需使用通配符?来返回任何类型... 因此getter返回List<String, ?> - 这里的?可以是任何类型的对象。

英文:

I'd wrap the Map&lt;String, List&lt;String&gt;&gt; in a new class with a getter, let's call it MapAsString. Make it part of a class hierarchy so you have class MapAsString extends DataMap. Next have a new class that is a subclass of DataMap called perhaps MapAsLocalTime where MapAsLocalTime extends DataMap.

Bonus points: make your parent class DataMap abstract and provide a single abstract method you must implement. that uses Generics to return a List&lt;String, T&gt;. You can have a constructor that takes a T (generic type) which defines what type T will be at construction time. If this seems too hard, perhaps just have it return anything using the wildcard ?... so getter returns List&lt;String, ?&gt; - here ? can an object of any type

答案3

得分: 0

interface Parser<T> {
    public Map<String, List<T>> parse() throws IOException;
}

class RacerInfoParser implements Parser<String> {

    private final Path path;

    public RacerInfoParser(Path path) {
        this.path = path;
    }

    @Override
    public Map<String, List<String>> parse() throws IOException {
        try (Stream<String> lines = Files.lines(path)){

            Map<String, List<String>> map = lines.collect(Collectors.toMap(
                    string -> string.substring(0, 3),
                    string -> Arrays.asList(string.substring(4).split("_"))));
            return map;
        }
    }
}

class TimeParser implements Parser<LocalTime> {

    private final Path path;

    public TimeParser(Path path) {
        this.path = path;
    }

    @Override
    public Map<String, List<LocalTime>> parse() throws IOException {
        try (Stream<String> lines = Files.lines(path)){

            Map<String, List<LocalTime>> result = lines.collect(Collectors.toMap(
                    string -> string.substring(0, 3),
                    string -> Arrays.stream(string.substring(4).split("_"))
                            .map(LocalTime::parse)
                            .collect(Collectors.toList())
            ));
            return result;
        }
    }
}
英文:

You can use generics T. Like this way

interface Parser&lt;T&gt; {
public Map&lt;String, List&lt;T&gt;&gt; parse() throws IOException;
}
class RacerInfoParser implements Parser&lt;String&gt;{
private final Path path;
public RacerInfoParser(Path path) {
this.path = path;   
}
@Override
public Map &lt;String, List&lt;String&gt;&gt; parse() throws IOException {
try (Stream&lt;String&gt;lines = Files.lines(path)){
Map &lt;String,  List&lt;String&gt;&gt; map = lines.collect(Collectors.toMap(
string -&gt; string.substring(0,3),
string -&gt; Arrays.asList(string.substring(4).split(&quot;_&quot;))));
return map;
}
}
}
class TimeParser implements Parser&lt;LocalTime&gt; {
private final Path path;
public TimeParser(Path path) {
this.path = path;   
}
@Override
public Map &lt;String, List&lt;LocalTime&gt;&gt; parse() throws IOException {
try (Stream&lt;String&gt;lines = Files.lines(path)){
Map&lt;String, List&lt;LocalTime&gt;&gt; result = lines.collect(Collectors.toMap(
string -&gt; string.substring(0,3),
string -&gt; Arrays.stream(string.substring(4).split(&quot;_&quot;))
.map(LocalTime::parse)
.collect(Collectors.toList())
));
return result;
}
}
}

huangapple
  • 本文由 发表于 2020年10月14日 16:56:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/64349852.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定