「いいね!」機能では MySQL と Redis のどちらを使用すればよいでしょうか?

「いいね!」機能では MySQL と Redis のどちらを使用すればよいでしょうか?

これは私が最近受けた面接での質問です。このブログではこの質問を要約して共有します。

1. 初心者が陥りがちな間違い

おそらく多くの初心者(当時の私も含めて、笑)は、まず次のようなことを書こうと考えるでしょう。

パブリック静的voidメイン(String[] args) {
    リスト<String> プラットフォームリスト = 新しい ArrayList<>();
    platformList.add("博客园");
    プラットフォームリストに「CSDN」を追加します。
    プラットフォームリストに「ナゲット」を追加します。
 
    for (文字列プラットフォーム:プラットフォームリスト) {
        if (platform.equals("博客园")) {
            プラットフォームを削除します。
        }
    }
 
    System.out.println(プラットフォームリスト);
}

自信を持って実行してみましたが、
java.util.ConcurrentModificationException は例外であり、中国語で同時変更例外を意味します。

機能と同様: MySQL または Redis を使用しますか?

なぜこのようなことが起こるのかと混乱して疑問に思っていませんか?

まず、上記のコードによって生成されたバイトコードを見てみましょう。

機能と同様: MySQL または Redis を使用しますか?

このことから、foreach ループが実際に実行されると、実際には Iterator が使用され、使用されるコア メソッドは hasnext() と next() であることがわかります。

それでは、ArrayList クラスの Iterator がどのように実装されているかを見てみましょう。

機能と同様: MySQL または Redis を使用しますか?

次の要素を取得するために next() メソッドが呼び出されると、コードの最初の行は checkForComodification(); を呼び出すことであり、このメソッドのコアロジックは 2 つの変数 modCount と expectedModCount の値を比較することであることがわかります。

上記の例では、最初は modCount と expectedModCount の値が両方とも 3 であるため、要素「博客园」を初めて取得する際に問題はありませんが、次のコード行が実行されると:

プラットフォームを削除します。

modCountの値が4に変更されます。

機能と同様: MySQL または Redis を使用しますか?

そのため、2 回目に要素を取得するときに、modCount と expectedModCount の値が等しくないため、エラーがスローされます。
java.util.ConcurrentModificationException。

機能と同様: MySQL または Redis を使用しますか?

foreach を使用してこれを実現することはできないので、どのように実装すればよいでしょうか?

主な方法は3つあります。

  • Iteratorのremove()メソッドの使用
  • 正の順序で走査するには for ループを使用します
  • 逆順に移動するには for ループを使用します

次に一つずつ説明していきます。

2. Iteratorのremove()メソッドを使用する

Iterator を使用した remove() メソッドの実装は次のとおりです。

パブリック静的voidメイン(String[] args) {
    リスト<String> プラットフォームリスト = 新しい ArrayList<>();
    platformList.add("博客园");
    プラットフォームリストに「CSDN」を追加します。
    プラットフォームリストに「ナゲット」を追加します。
 
    イテレータ<String> iterator = platformList.iterator();
    (イテレータ.hasNext()) の間 {
        文字列プラットフォーム = iterator.next();
        if (platform.equals("博客园")) {
            イテレータを削除します。
        }
    }
 
    System.out.println(プラットフォームリスト);
}

出力は次のようになります。

[CSDN、ナゲッツ]

iterator.remove() が使用できるのはなぜですか?ソースコードを見てみましょう:

機能と同様: MySQL または Redis を使用しますか?

要素が削除されるたびに、modCountの値がexpectedModCountに再割り当てされ、2つの変数が等しくなり、トリガーされないことがわかります。
java.util.ConcurrentModificationException。その他の面接の質問については、公式アカウントJava Interview Questions Selectionをフォローしてください。

3. forループを使用して正の順序で走査する

for ループを使用した前方トラバーサルの実装は次のとおりです。

パブリック静的voidメイン(String[] args) {
    リスト<String> プラットフォームリスト = 新しい ArrayList<>();
    platformList.add("博客园");
    プラットフォームリストに「CSDN」を追加します。
    プラットフォームリストに「ナゲット」を追加します。
 
    (int i = 0; i < platformList.size(); i++) の場合 {
        文字列項目 = platformList.get(i);
 
        if (item.equals("博客园")) {
            プラットフォームリストを削除します(i);
            i = i - 1;
        }
    }
 
    System.out.println(プラットフォームリスト);
}

この実装は配列の添字で削除するだけなので比較的理解しやすいのですが、要素を削除した後は添字の値を修正する必要があるという注意点があります。

i = i - 1;

下付き文字の値を修正する必要があるのはなぜですか?最初の要素の添え字は次のようになります。

機能と同様: MySQL または Redis を使用しますか?

最初のループで要素「博客园」を削除すると、要素の添え字は次のようになります。

機能と同様: MySQL または Redis を使用しますか?

2 番目のループでは、i の値は 1 です。これは、要素 "Nuggets" が取得され、要素 "CSDN" がスキップされることを意味します。したがって、要素を削除した後、添え字を修正する必要があります。これは、上記のコードで i = i - 1; の目的でもあります。インタビューの質問の詳細については、WeChatのサブスクリプション番号Jiangjijiをフォローしてインタビューに返信してください。

4. forループを使用して逆順に走査する

for ループを使用した逆方向トラバーサルの実装は次のとおりです。

パブリック静的voidメイン(String[] args) {
    リスト<String> プラットフォームリスト = 新しい ArrayList<>();
    platformList.add("博客园");
    プラットフォームリストに「CSDN」を追加します。
    プラットフォームリストに「ナゲット」を追加します。
 
    (int i = platformList.size() - 1; i >= 0; i--) {
        文字列項目 = platformList.get(i);
 
        if (item.equals("ナゲット")) {
            プラットフォームリストを削除します(i);
        }
    }
 
    System.out.println(プラットフォームリスト);
}

この実装は、for ループを使用して前方順にトラバースするのと似ていますが、先頭の要素の添え字は次のようになるため、添え字を修正する必要はありません。

機能と同様: MySQL または Redis を使用しますか?

最初のループで要素「Nuggets」を削除すると、要素の添え字は次のようになります。

機能と同様: MySQL または Redis を使用しますか?

2 番目のループでは、i の値が 1 であるため、要素 "CSDN" が取得され、要素がスキップされることはないため、添え字を修正する必要はありません。

そのため、2 回目に要素を取得するときに、modCount と expectedModCount の値が等しくないため、エラーがスローされます。
java.util.ConcurrentModificationException。

機能と同様: MySQL または Redis を使用しますか?

foreach を使用してこれを実現することはできないので、どのように実装すればよいでしょうか?

主な方法は3つあります。

  • Iteratorのremove()メソッドの使用
  • 正の順序で走査するには for ループを使用します
  • 逆順に移動するには for ループを使用します

次に一つずつ説明していきます。

5. Iteratorのremove()メソッドを使用する

Iterator を使用した remove() メソッドの実装は次のとおりです。

パブリック静的voidメイン(String[] args) {
    リスト<String> プラットフォームリスト = 新しい ArrayList<>();
    platformList.add("博客园");
    プラットフォームリストにCSDNを追加します。
    プラットフォームリストに「ナゲット」を追加します。
 
    イテレータ<String> iterator = platformList.iterator();
    (イテレータ.hasNext()) の間 {
        文字列プラットフォーム = iterator.next();
        if (platform.equals("博客园")) {
            イテレータを削除します。
        }
    }
 
    System.out.println(プラットフォームリスト);
}

出力は次のようになります。

[CSDN、ナゲッツ]

iterator.remove() が使用できるのはなぜですか?ソースコードを見てみましょう:

機能と同様: MySQL または Redis を使用しますか?

要素が削除されるたびに、modCountの値がexpectedModCountに再割り当てされ、2つの変数が等しくなり、トリガーされないことがわかります。
java.util.ConcurrentModificationException。その他の面接の質問については、公式アカウントJava Interview Questions Selectionをフォローしてください。

6. forループを使用して正の順序で走査する

for ループを使用した前方トラバーサルの実装は次のとおりです。

パブリック静的voidメイン(String[] args) {
    リスト<String> プラットフォームリスト = 新しい ArrayList<>();
    platformList.add("博客园");
    プラットフォームリストに「CSDN」を追加します。
    プラットフォームリストに「ナゲット」を追加します。
 
    (int i = 0; i < platformList.size(); i++) の場合 {
        文字列項目 = platformList.get(i);
 
        if (item.equals("博客园")) {
            プラットフォームリストを削除します(i);
            i = i - 1;
        }
    }
 
    System.out.println(プラットフォームリスト);
}

この実装は配列の添字で削除するだけなので比較的理解しやすいのですが、要素を削除した後は添字の値を修正する必要があるという注意点があります。

i = i - 1;

下付き文字の値を修正する必要があるのはなぜですか?最初の要素の添え字は次のようになります。

機能と同様: MySQL または Redis を使用しますか?

最初のループで要素「博客园」を削除すると、要素の添え字は次のようになります。

機能と同様: MySQL または Redis を使用しますか?

2 番目のループでは、i の値は 1 です。これは、要素 "Nuggets" が取得され、要素 "CSDN" がスキップされることを意味します。したがって、要素を削除した後、添え字を修正する必要があります。これは、上記のコードで i = i - 1; の目的でもあります。インタビューの質問の詳細については、WeChatのサブスクリプション番号Jiangjijiをフォローしてインタビューに返信してください。

7. forループを使用して逆順に走査する

for ループを使用した逆方向トラバーサルの実装は次のとおりです。

パブリック静的voidメイン(String[] args) {
    リスト<String> プラットフォームリスト = 新しい ArrayList<>();
    platformList.add("博客园");
    プラットフォームリストに「CSDN」を追加します。
    プラットフォームリストに「ナゲット」を追加します。
 
    (int i = platformList.size() - 1; i >= 0; i--) {
        文字列項目 = platformList.get(i);
 
        if (item.equals("ナゲット")) {
            プラットフォームリストを削除します(i);
        }
    }
 
    System.out.println(プラットフォームリスト);
}

この実装は、for ループを使用して前方順にトラバースするのと似ていますが、先頭の要素の添え字は次のようになるため、添え字を修正する必要はありません。

機能と同様: MySQL または Redis を使用しますか?

最初のループで要素「Nuggets」を削除すると、要素の添え字は次のようになります。

機能と同様: MySQL または Redis を使用しますか?

2 番目のループでは、i の値が 1 であるため、要素 "CSDN" が取得され、要素がスキップされることはないため、添え字を修正する必要はありません。

いいね機能にMySQLとRedisのどちらを使うべきかについてはこれで終わりです。MySQL\Redisのいいね機能に関する関連コンテンツについては、123WORDPRESS.COMの過去の記事を検索するか、以下の関連記事を引き続きご覧ください。今後とも123WORDPRESS.COMをよろしくお願いいたします。

以下もご興味があるかもしれません:
  • thinkphp5を使ってredisを操作し、記事の人気ランキングやいいねランキングを実装する例
  • Redis を使用していいねといいねの取り消しを実装するための詳細なコード
  • Redis キャッシュを使用して「いいね」と「いいねなし」を実装するためのサンプル コード
  • Springboot + redis は、いいね、閲覧、お気に入り、コメントなどの数の増減操作を実装します。
  • Redisベースのlike関数の設計思想の詳細な説明
  • Redisを使用してlike関数を実装し、データベースと同期する方法を段階的に説明します。

<<:  Webフロントエンド開発エンジニアが習得すべきコアスキル

>>:  HTML のボタン タグをクリックしてページにジャンプする 3 つの方法

推薦する

MySQL ベースのシーケンス実装方法

チームは新しいフレームを交換しました。すべての新しいビジネスでは、新しいフレームワークと新しいデータ...

aタグのname属性とid属性を使用してページ内を移動する方法

以前はaタグのname属性を使ってジャンプする方法しか知らなかったのですが、idも使えることを今日知...

Docker Gitlab+Jenkins+Harborは永続的なプラットフォーム運用を構築します

CI/CD の概要CIワークフロー設計Gitコードバージョン管理システムはコマンドラインでのみ管理で...

Linux で指定されたフォルダの各サブフォルダ内のファイル数を表示する

カウントスクリプト #!/bin/sh 引数の数=$# [ $numOfArgs -ne 1 ]の場...

MYSQLでプロシージャの名前を変更する方法の詳細な説明

最近、ストアド プロシージャの名前を変更する機能を使用しました。インターネットで情報を検索しましたが...

SQLはLeetCodeを実装します(180.連続した数字)

[LeetCode] 180. 連続した数字少なくとも 3 回連続して出現するすべての数字を検索す...

MySQL 5.7.20 解凍版のインストールとルートパスワードの変更に関するチュートリアル

1. MySQL アーカイブ (解凍版) をダウンロードするURL: https://downloa...

crontab でスケジュールされたタスクが実行されない理由の概要

序文最近、仕事でいくつかの問題が発生しました。crontab でスケジュールされたタスクが実行されま...

docker を使用して minio と java sdk を構築するプロセスの詳細な説明

目次1minioはシンプル2 Dockerビルド minio 2.1 単一ノード2.2 マルチノード...

DockerにMySQL 8.0をインストールする方法

環境: MacOS_Cetalina_10.15.1、Mysql8.0.18、Docker_2.0....

MySQL ストレステストツール Mysqlslap の使用

1. MySQL独自のストレステストツールMysqlslap mysqlslap は、mysql に...

MySQL でレプリケーション フィルターを動的に変更する方法

MySQLはレプリケーションフィルターを動的に変更します今日遭遇した問題についてお話しします。今日は...

vue フロントエンド HbuliderEslint リアルタイム検証 自動修復設定

目次HBuilderX での ESLint プラグインのインストールカスタム eslint-js ル...

CentOS7.6 システムで yum を使用して lnmp 環境を構成する方法

1. インストールバージョンの詳細 サーバー: MariaDB サーバーバージョン: 5.5.60-...