簡體   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