繁体   English   中英

如何有效地检查来自缓冲阅读器的读取行是否包含来自枚举列表的字符串

[英]How to efficiently check if read line from Buffered reader contains a string from an enum list

我是一名计算机科学专业的大学生,在课外从事我的第一个“大”项目。 我正在尝试使用缓冲阅读器逐行读取大型文本文件(2,000 - 3,000 行文本)。 当找到枚举列表中的关键字时,我希望它将当前行从缓冲读取器发送到其适当的方法以进行适当的处​​理。

我有一个解决方案,但我的直觉是有一种更好的方法来处理这种情况。 任何建议或反馈将不胜感激。

当前解决方案我正在遍历枚举列表,然后使用 String.contains 方法检查当前枚举的 toString 返回是否在缓冲读取器的当前行中。 如果找到了枚举,则在适当的方法调用的 switch 语句中使用枚举。 (我总共有 13 个案例只是想保持代码示例简短)。

try (BufferedReader reader = new BufferedReader(new FileReader(inputFile.getAbsoluteFile()))){

    while ((currentLine = reader.readLine()) != null) {
        
        for (GameFileKeys gameKey : GameFileKeys.values()) {
            
            if (currentLine.contains(gameKey.toString())) {
                switch (gameKey) {
                    case SEAT -> seatAndPlayerAssignment(currentTableArr, currentLine);
                    case ANTE -> playerJoinLate(currentLine);
                }
            }
        }
    }
}

以前的解决方案最初,我有一个令人讨厌的 if 语句列表,检查当前行是否包含关键字之一,然后适当地处理它。 显然这远非最优,但我的直觉告诉我,我目前的解决方案也不是最优的。


try (BufferedReader reader = new BufferedReader(new FileReader(inputFile.getAbsoluteFile()))){

    while ((currentLine = reader.readLine()) != null) {
        
        if(currentLine.contains(GameFileKey.SEAT){
            seatAndPlayerAssignment(currentTableArr, currentLine);
        }
        else if(currentLine.contains(GameFileKey.ANTE){
            playerJoinLate(currentLine);           
        }
    }
}

枚举类如果你需要这个,或者对我如何实现我的枚举有任何一般性的反馈。

public enum GameFileKeys {
    ANTE("posts ante"),
    SEAT("Seat ");

    private final String gameKey;

    GameFileKeys(String str) {
        this.gameKey = str;
    }

    @Override
    public String toString() {
        return gameKey;
    }
}

我无法改进代码的核心:枚举的values()循环,为每个枚举对象的字符串执行String#contains ,并使用switch 我可以提几个小建议。

我建议您不要覆盖枚举上的toString方法。 Object#toString方法通常最好仅用于调试和记录,而不是逻辑或表示。

您传递给枚举构造函数的字符串可能类似于此类枚举中常见的显示名称的想法。 正式的枚举名称(全部大写)在 Java 内部使用,而显示名称用于向用户显示或与外部系统交换。 请参阅MonthDayOfWeek枚举作为提供getDisplayName方法的示例。

此外,枚举应该以单数命名。 这避免了与枚举对象的任何集合的混淆。

顺便说一句,看起来你的第二个枚举参数中有一个杂散的空格。

起初我认为拥有所有显示名称的列表以及显示名称到枚举对象的映射会有所帮助。 但是,最终,您的目的都不需要。 我保留了这些,因为它们可能会很有趣。

public enum GameFileKey
{
    ANTE( "posts ante" ),
    SEAT( "Seat" );

    private String displayName = null;

    private static final List < String > allDisplayNames = Arrays.stream( GameFileKey.values() ).map( GameFileKey :: getDisplayName ).toList();
    private static final Map < String, GameFileKey > mapOfDisplayNameToGameFileKey = Arrays.stream( GameFileKey.values() ).collect( Collectors.toUnmodifiableMap( GameFileKey :: getDisplayName , Function.identity() ) );

    GameFileKey ( String str ) { this.displayName = str; }

    public String getDisplayName ( ) { return this.displayName; }

    public static GameFileKey forDisplayName ( final String displayName )
    {
        return
                Objects.requireNonNull(
                        GameFileKey.mapOfDisplayNameToGameFileKey.get( displayName ) ,
                        "None of the " + GameFileKey.class.getCanonicalName() + " enum objects has a display name of: " + displayName + ". Message # 4dcefee2-4aa2-48cf-bf66-9a4bde02ac37." );
    }

    public static List < String > allDisplayNames ( ) { return GameFileKey.allDisplayNames; }
}

您可以使用正在处理的文件的行流。 仅供参考,不一定比您的代码更好。

public class Demo
{
    public static void main ( String[] args )
    {
        Demo app = new Demo();
        app.demo();
    }

    private void demo ( )
    {
        try
        {
            Path path = Demo.getFilePathToRead();
            Stream < String > lines = Files.lines( path );
            lines.forEach(
                    line -> {
                        for ( GameFileKey gameKey : GameFileKey.values() )
                        {
                            if ( line.contains( gameKey.getDisplayName() ) )
                            {
                                switch ( gameKey )
                                {
                                    case SEAT -> this.seatAndPlayerAssignment( line );
                                    case ANTE -> this.playerJoinLate( line );
                                }
                            }
                        }
                    }
            );
        }
        catch ( IOException e )
        {
            throw new RuntimeException( e );
        }
    }

    private void playerJoinLate ( String line )
    {
        System.out.println( "line = " + line );
    }

    private void seatAndPlayerAssignment ( String line )
    {
        System.out.println( "line = " + line );
    }

    public static Path getFilePathToRead ( ) throws IOException
    {
        Path tempFile = Files.createTempFile( "bogus" , ".txt" );
        Files.write( tempFile , "apple\nSeat\norange\nposts ante\n".getBytes() );
        return tempFile;
    }
}

运行时:

线 = 座位

线=发布赌注

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM