ホームページ Java &#&チュートリアル Java を使用してレコメンデーション システム ベースのソーシャル ネットワーク アプリケーションを作成する方法

Java を使用してレコメンデーション システム ベースのソーシャル ネットワーク アプリケーションを作成する方法

Jun 27, 2023 am 08:32 AM
推奨システム Javaプログラミング ソーシャルネットワーク

現代のソーシャル ネットワーク アプリケーションでは、レコメンデーション システムが不可欠な機能になっています。ユーザーに友達を勧めたり、興味のあるトピックを勧めたり、関連製品を勧めたり、より価値のあるコンテンツを勧めたりする場合でも、レコメンデーション システムはユーザー エクスペリエンスと継続性を効果的に向上させることができます。

この記事では、Java を使用してレコメンデーション システムに基づいたソーシャル ネットワーク アプリケーションを作成する方法を紹介します。実際のコードと詳細な手順を組み合わせて、読者が基本的なレコメンデーション システムをすぐに理解して実装できるようにします。

1. データの収集と処理

レコメンデーション システムを実装する前に、大量のデータを収集して処理する必要があります。ソーシャル ネットワーク アプリケーションでは、ユーザー情報、投稿、コメント、いいね! などのデータはすべて貴重なデータ ソースです。

デモンストレーションを容易にするために、オープンソースの仮想データ ジェネレーターを使用してこれらのデータを生成できます。具体的な手順は次のとおりです。

  1. Mockaroo (https://www.mockaroo.com/) などの仮想データ ジェネレーターをダウンロードしてインストールします。
  2. ユーザー情報、投稿、コメントなど、生成する必要があるデータセットを定義します。
  3. データを生成し、CSV ファイルにエクスポートします。
  4. Java コードを使用して、CSV ファイル内のデータを読み取り、データベースに保存します。 MySQL や Oracle などの一般的なリレーショナル データベースを使用してデータを保存できます。ここでは、データ保存用のデータベースとして MySQL 8.0 を使用します。

2. ユーザーとアイテムの表現

レコメンデーション システムでは、ユーザーとアイテムの類似性を計算したり、レコメンデーションを作成したりするために、ユーザーとアイテムをベクトルまたは行列形式に変換する必要があります。ソーシャル ネットワーク アプリケーションでは、次のメソッドを使用してユーザーとアイテムを表すことができます:

  1. ユーザー ベクトル: ユーザーがフォローしているトピック、公開する投稿、やり取りする友人などのデータを使用できます。ユーザーのベクトル。たとえば、ユーザー A が Java、Python、JavaScript などのトピックをフォローし、「Java を上手に学ぶ方法」および「Java 入門」を投稿し、ユーザー B および C と対話する場合、次のベクトルを使用できます。ユーザー A を表す場合:

ユーザー A = [1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0 , 0, 1, 0, 0, 1]

ベクトルの長さは 24 で、各位置はトピックまたは投稿を表します。 1 はユーザー A がトピックをフォローしたか、投稿を公開したことを意味し、0 はフォローしていないことを意味します。

  1. アイテム ベクトル: 各投稿のタグ、コンテンツ、コメント、その他のデータを使用して、投稿のベクトルを表すことができます。たとえば、投稿に「Java、プログラミング」というタグが付けられ、内容が「Java プログラミングを学習するための 4 つの提案」で 10 件のコメントがある場合、次のベクトルを使用して投稿を表すことができます。 #Post A = [1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10 , 0]
ベクトルの長さは 24 で、各位置はラベルまたは統計データを表します。 1 は投稿にタグまたはコンテンツが含まれていることを意味し、0 は含まれていないことを意味します。

3. ユーザーベースの協調フィルタリングの推奨

ユーザーベースの協調フィルタリングは、推奨システムの一般的な方法であり、ユーザーの関心の類似性に基づいてアイテムを推奨します。ここでは、ユーザーベースの協調フィルタリングを使用して、ユーザーに適切な投稿を推奨します。具体的な手順は次のとおりです。

ユーザー間の類似性を計算します。ここでは、類似性メトリックとしてピアソン相関係数を使用します。

    ターゲット ユーザーとの関心の類似性が最も高い K 人のユーザーを選択します。
  1. 各ユーザーについて、気に入っているが対象ユーザーには見られていない投稿を N 個選択します。
  2. 選択した N 個の投稿について、各投稿の推奨スコアを計算し、高いものから低いものへ並べ替えます。
  3. スコアが最も高い上位 M 個の投稿を推奨結果として選択します。
  4. 次は、アルゴリズムの Java コード実装です:
  5. public class CollaborativeFiltering {
    
        /**
         * 计算用户间的皮尔逊相关系数
         * @param user1 用户1
         * @param user2 用户2
         * @param data 数据集
         * @return 皮尔逊相关系数
         */
        public double pearsonCorrelation(Map<Integer, Double> user1, Map<Integer, Double> user2,
                                          Map<Integer, Map<Integer, Double>> data) {
            double sum1 = 0, sum2 = 0, sum1Sq = 0, sum2Sq = 0, pSum = 0;
            int n = 0;
            for (int item : user1.keySet()) {
                if (user2.containsKey(item)) {
                    sum1 += user1.get(item);
                    sum2 += user2.get(item);
                    sum1Sq += Math.pow(user1.get(item), 2);
                    sum2Sq += Math.pow(user2.get(item), 2);
                    pSum += user1.get(item) * user2.get(item);
                    n++;
                }
            }
            if (n == 0)
                return 0;
            double num = pSum - (sum1 * sum2 / n);
            double den = Math.sqrt((sum1Sq - Math.pow(sum1, 2) / n) *
                    (sum2Sq - Math.pow(sum2, 2) / n));
            if (den == 0)
                return 0;
            return num / den;
        }
    
        /**
         * 基于用户的协同过滤推荐算法
         * @param data 数据集
         * @param userId 目标用户 ID
         * @param K 最相似的 K 个用户
         * @param N 推荐的 N 个帖子
         * @return 推荐的帖子 ID 列表
         */
        public List<Integer> userBasedCollaborativeFiltering(Map<Integer, Map<Integer, Double>> data,
                                                              int userId, int K, int N) {
            Map<Integer, Double> targetUser = data.get(userId); // 目标用户
            List<Map.Entry<Integer, Double>> similarUsers = new ArrayList<>(); // 与目标用户兴趣相似的用户
            for (Map.Entry<Integer, Map<Integer, Double>> entry: data.entrySet()) {
                int id = entry.getKey();
                if (id == userId)
                    continue;
                double sim = pearsonCorrelation(targetUser, entry.getValue(), data); // 计算皮尔逊相关系数
                if (sim > 0)
                    similarUsers.add(new AbstractMap.SimpleEntry<>(id, sim));
            }
            Collections.sort(similarUsers, (a, b) -> b.getValue().compareTo(a.getValue())); // 按相似度从高到低排序
            List<Integer> itemIds = new ArrayList<>();
            for (int i = 0; i < K && i < similarUsers.size(); i++) {
                Map.Entry<Integer, Double> entry = similarUsers.get(i);
                int userId2 = entry.getKey();
                Map<Integer, Double> user2 = data.get(userId2);
                for (int itemId: user2.keySet()) {
                    if (!targetUser.containsKey(itemId)) { // 如果目标用户没看过该帖子
                        itemIds.add(itemId);
                    }
                }
            }
            Map<Integer, Double> scores = new HashMap<>();
            for (int itemId: itemIds) {
                double score = 0;
                int count = 0;
                for (Map.Entry<Integer, Double> entry: similarUsers) {
                    int userId2 = entry.getKey();
                    Map<Integer, Double> user2 = data.get(userId2);
                    if (user2.containsKey(itemId)) { // 如果用户 2 看过该帖子
                        score += entry.getValue() * user2.get(itemId);
                        count++;
                        if (count == N)
                            break;
                    }
                }
                scores.put(itemId, score);
            }
            List<Integer> pickedItemIds = new ArrayList<>();
            scores.entrySet().stream().sorted((a, b) -> b.getValue().compareTo(a.getValue()))
                    .limit(N).forEach(entry -> pickedItemIds.add(entry.getKey())); // 按得分从高到低排序并选出前N个
            return pickedItemIds;
        }
    }
    ログイン後にコピー
4. コンテンツ ベースの推奨アルゴリズム

コンテンツ ベースの推奨アルゴリズムは、別のタイプの推奨アルゴリズムです。推奨システム: 属性の類似性に基づいて項目を推奨する一般的な方法。ここでは、コンテンツベースの推奨アルゴリズムを使用して、適切な投稿をユーザーに推奨します。具体的な手順は次のとおりです。

対象ユーザーについては、フォローしているトピックや公開する投稿などを選択します。

    これらの内容をもとに、各投稿と対象ユーザーの興味関心との類似度を計算します。
  1. ターゲット ユーザーの興味に最も近い上位 N 個の投稿を選択します。
  2. スコアの高いものから低いものの順に並べ替え、スコアが最も高い上位 M 件の投稿を推奨結果として選択します。
  3. 以下は、コンテンツベースの推奨アルゴリズムの Java コード実装です:
  4. public class ContentBasedRecommendation {
    
        /**
         * 计算两个向量的余弦相似度
         * @param v1 向量1
         * @param v2 向量2
         * @return 余弦相似度
         */
        public double cosineSimilarity(double[] v1, double[] v2) {
            double dotProduct = 0;
            double norma = 0;
            double normb = 0;
            for (int i = 0; i < v1.length; i++) {
                dotProduct += v1[i] * v2[i];
                norma += Math.pow(v1[i], 2);
                normb += Math.pow(v2[i], 2);
            }
            if (norma == 0 || normb == 0)
                return 0;
            return dotProduct / (Math.sqrt(norma) * Math.sqrt(normb));
        }
    
        /**
         * 基于内容的推荐算法
         * @param data 数据集
         * @param userId 目标用户 ID
         * @param N 推荐的 N 个帖子
         * @return 推荐的帖子 ID 列表
         */
        public List<Integer> contentBasedRecommendation(Map<Integer, Map<Integer, Double>> data,
                                                         int userId, int N) {
            Map<Integer, Double> targetUser = data.get(userId); // 目标用户
            int[] pickedItems = new int[data.size()];
            double[][] itemFeatures = new double[pickedItems.length][24]; // 物品特征矩阵
            for (Map.Entry<Integer, Map<Integer, Double>> entry: data.entrySet()) {
                int itemId = entry.getKey();
                Map<Integer, Double> item = entry.getValue();
                double[] feature = new double[24];
                for (int i = 0; i < feature.length; i++) {
                    if (item.containsKey(i+1)) {
                        feature[i] = item.get(i+1);
                    } else {
                        feature[i] = 0;
                    }
                }
                itemFeatures[itemId-1] = feature; // 物品 ID 从 1 开始,需要减一
            }
            for (int itemId: targetUser.keySet()) {
                pickedItems[itemId-1] = 1; // 物品 ID 从 1 开始,需要减一
            }
            double[] similarities = new double[pickedItems.length];
            for (int i = 0; i < similarities.length; i++) {
                if (pickedItems[i] == 0) {
                    similarities[i] = cosineSimilarity(targetUser.values().stream().mapToDouble(Double::doubleValue).toArray(), itemFeatures[i]);
                }
            }
            List<Integer> itemIds = new ArrayList<>();
            while (itemIds.size() < N) {
                int maxIndex = -1;
                for (int i = 0; i < similarities.length; i++) {
                    if (pickedItems[i] == 0 && (maxIndex == -1 || similarities[i] > similarities[maxIndex])) {
                        maxIndex = i;
                    }
                }
                if (maxIndex == -1 || similarities[maxIndex] < 0) {
                    break; // 找不到更多相似的物品了
                }
                itemIds.add(maxIndex + 1); // 物品 ID 从 1 开始,需要加一
                pickedItems[maxIndex] = 1;
            }
            Map<Integer, Double> scores = new HashMap<>();
            for (int itemId: itemIds) {
                double[] features = itemFeatures[itemId-1]; // 物品 ID 从 1 开始,需要减一
                double score = cosineSimilarity(targetUser.values().stream().mapToDouble(Double::doubleValue).toArray(), features);
                scores.put(itemId, score);
            }
            List<Integer> pickedItemIds = new ArrayList<>();
            scores.entrySet().stream().sorted((a, b) -> b.getValue().compareTo(a.getValue()))
                    .limit(N).forEach(entry -> pickedItemIds.add(entry.getKey())); // 按得分从高到低排序并选出前N个
            return pickedItemIds;
        }
    }
    ログイン後にコピー
5. 推奨アルゴリズムをアプリケーションに統合します

上記の作業を完了した後、 2 つの推奨アルゴリズム 実装したら、アプリケーションに統合できます。具体的な手順は次のとおりです。

データをロードし、データベースに保存します。 Hibernate などの ORM フレームワークを使用すると、データベースへのアクセス操作を簡素化できます。

    HTTP リクエストを受け入れ、JSON 形式でレスポンスを返す RESTful API を定義します。 Spring Framework を使用して RESTful API を構築およびデプロイできます。
  1. ユーザーベースの協調フィルタリング推奨アルゴリズムとコンテンツベースの推奨アルゴリズムを実装し、RESTful API に統合します。
  2. 次は、アプリケーションの Java コード実装です:
  3. @RestController
    @RequestMapping("/recommendation")
    public class RecommendationController {
    
        private CollaborativeFiltering collaborativeFiltering = new CollaborativeFiltering();
        private ContentBasedRecommendation contentBasedRecommendation = new ContentBasedRecommendation();
    
        @Autowired
        private UserService userService;
    
        @GetMapping("/userbased/{userId}")
        public List<Integer> userBasedRecommendation(@PathVariable Integer userId) {
            List<User> allUsers = userService.getAllUsers();
            Map<Integer, Map<Integer, Double>> data = new HashMap<>();
            for (User user: allUsers) {
                Map<Integer, Double> userVector = new HashMap<>();
                List<Topic> followedTopics = user.getFollowedTopics();
                for (Topic topic: followedTopics) {
                    userVector.put(topic.getId(), 1.0);
                }
                List<Post> posts = user.getPosts();
                for (Post post: posts) {
                    userVector.put(post.getId() + 1000, 1.0);
                }
                List<Comment> comments = user.getComments();
                for (Comment comment: comments) {
                    userVector.put(comment.getId() + 2000, 1.0);
                }
                List<Like> likes = user.getLikes();
                for (Like like: likes) {
                    userVector.put(like.getId() + 3000, 1.0);
                }
                data.put(user.getId(), userVector);
            }
            List<Integer> itemIds = collaborativeFiltering.userBasedCollaborativeFiltering(data, userId, 5, 10);
            return itemIds;
        }
    
        @GetMapping("/contentbased/{userId}")
        public List<Integer> contentBasedRecommendation(@PathVariable Integer userId) {
            List<User> allUsers = userService.getAllUsers();
            Map<Integer, Map<Integer, Double>> data = new HashMap<>();
            for (User user: allUsers) {
                Map<Integer, Double> userVector = new HashMap<>();
                List<Topic> followedTopics = user.getFollowedTopics();
                for (Topic topic: followedTopics) {
                    userVector.put(topic.getId(), 1.0);
                }
                List<Post> posts = user.getPosts();
                for (Post post: posts) {
                    userVector.put(post.getId() + 1000, 1.0);
                }
                List<Comment> comments = user.getComments();
                for (Comment comment: comments) {
                    userVector.put(comment.getId() + 2000, 1.0);
                }
                List<Like> likes = user.getLikes();
                for (Like like: likes) {
                    userVector.put(like.getId() + 3000, 1.0);
                }
    ログイン後にコピー

以上がJava を使用してレコメンデーション システム ベースのソーシャル ネットワーク アプリケーションを作成する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

WeChat で削除された連絡先を回復する方法 (簡単なチュートリアルでは、削除された連絡先を回復する方法について説明します) WeChat で削除された連絡先を回復する方法 (簡単なチュートリアルでは、削除された連絡先を回復する方法について説明します) May 01, 2024 pm 12:01 PM

残念ながら、WeChat は広く使用されているソーシャル ソフトウェアであり、何らかの理由で特定の連絡先を誤って削除してしまうことがよくあります。ユーザーがこの問題を解決できるように、この記事では、削除された連絡先を簡単な方法で取得する方法を紹介します。 1. WeChat の連絡先削除メカニズムを理解します。これにより、削除された連絡先を取得できるようになります。WeChat の連絡先削除メカニズムでは、連絡先がアドレス帳から削除されますが、完全には削除されません。 2. WeChat の組み込みの「連絡先帳復元」機能を使用します。WeChat には、この機能を通じて以前に削除した連絡先をすばやく復元できる「連絡先帳復元」機能が用意されています。 3. WeChat 設定ページに入り、右下隅をクリックし、WeChat アプリケーション「Me」を開き、右上隅にある設定アイコンをクリックして設定ページに入ります。

Tantan で誰かをブラックリストに登録する方法 Tantan で誰かをブラックリストに登録する方法 Apr 07, 2024 pm 04:00 PM

Tantan で誰かをブロックする方法 Tantan では、友達を選択して直接ブロックできます。ほとんどのユーザーは Tantan で友達をブロックする方法を知りません。次に、Tantan で誰かをブロックする方法の画像を示します。テキスト チュートリアル、興味のあるユーザーは見に来てください! Tantanで相手をブロックする方法 1. まず、携帯電話のロックを解除し、デスクトップを開き、[Tantan] APPをクリックしてメインページに入ります; 2. 次に、Tantanメッセージメインページで、希望する友達のアバターをクリックしますブロックするには; 3. 次に、下の画像を入力します。表示されたインターフェイスで、右上隅にある 3 点アイコンを使用して特別な領域に入ります; 4. 最後に、オプション ボックスが下部にポップアップ表示されます。[追加先] を見つけます。ブラックリスト]をクリックし、相手をブラックリストに登録します。

TikTokで相手の本名を確認する方法 TikTokで相手の本名を確認する方法 Apr 02, 2024 am 08:40 AM

Douyin の広大なプラットフォームでは、すべてのユーザーが自分自身を表現したり、内なる憧れを表現したり、物事への愛情を伝えたりするためにパーソナライズされたニックネームを使用することを好みますが、場合によっては、その友人が現実の友人である可能性があることに気づくことがあります。誰もが好奇心を持ち、本当の名前が彼らの知っている誰かであるかどうかを確認したかったのです。では、Douyin で本名を確認するにはどうすればよいでしょうか? 次のチュートリアルで詳しく説明しますので、お役に立てれば幸いです。 Douyinで相手の本名を確認する方法. 最初のステップは、Douyinアプリのフォローリストを開き、表示したい友達のアバターをクリックすることです。ステップ 2: 次に、ユーザーのホームページに移動し、ノート名をクリックします。ステップ 3: ポップアップ メニューで [名前の表示] をクリックします。

Weibo でサンシャイン クレジット スコアを向上させる方法_Weibo でサンシャイン クレジット スコアを向上させる方法のまとめ Weibo でサンシャイン クレジット スコアを向上させる方法_Weibo でサンシャイン クレジット スコアを向上させる方法のまとめ Mar 30, 2024 pm 04:26 PM

1. Weibo を開き、「Discover」をクリックし、「More Hot Searches」をクリックして、ホット検索リストを見つけます (図を参照)。 2. 入力するホット検索トピックを選択します (図を参照)。 3. ホット検索の下にある [一緒にディスカッション] をクリックし、ホット検索のトピックを Weibo に投稿します (図を参照)。方法 2: 個人情報を入力します。 1. Weibo を開き、個人のホームページに入り、下ボタン アイコンをクリックします (図を参照)。 2. をクリックして基本情報を表示および編集し、編集に入ります (図を参照)。方法 3: 信頼度の高い、大きな V ファンと小さな V ファンを持つユーザーを増やし、相互に交流します。 1. ホームページを開いて影響力のあるブロガーを確認し、下のコメントをクリックして対話します (図を参照)。方法 4: Weibo で慈善寄付に参加します。 1. [My] をクリックして、私のウォレットを入力します (図を参照)。 2:00

2024 年 5 月に注目すべき 6 つのエアドロップ プロジェクトの一覧 2024 年 5 月に注目すべき 6 つのエアドロップ プロジェクトの一覧 May 05, 2024 am 09:04 AM

2024.5 年に注目に値する他のエアドロップ プロジェクトは何ですか?注目のエアドロッププロジェクト6選! 5月にいくつかのエアドロップチェイサーは他のターゲット、つまりネイティブトークンを持たないDeFiプロトコルに目を向けています。この期待により、ユーザーがエアドロップの準備をする際にプラットフォームに流動性が流入することがよくあります。現在の市場の低迷により、今年初めの暗号トークンの価格上昇は妨げられましたが、希望を集めているプロジェクトがいくつかあります。今日は、このウェブサイトの編集者が、皆さんがすぐにお金を稼げるよう、注目に値する 6 つのエアドロップ プロジェクトを詳しく紹介します。 Airdrop 希望者はトークンレス プロジェクトの開発を続けています。暗号通貨は投資家の預金を押し上げています。エアドロップの受信者は、トークン配布の可能性を否定しようとするプロジェクト チームの試みに動揺しませんでした。 4 月はエアドロップにとって重要な月です

mongodb に保存するにはどのようなデータが適していますか? mongodb に保存するにはどのようなデータが適していますか? Apr 02, 2024 pm 12:24 PM

MongoDB は、次のようなさまざまなタイプのデータの保存に適しています。 非構造化データおよび半構造化データ 複雑な関係を持つデータ ビッグデータ データセット 時系列データ 地理空間データ その他: バイナリデータ、Web データ、メタデータ

ソラナとビットコインの違い ソラナとビットコインの違い Apr 30, 2024 pm 02:18 PM

Solana と Bitcoin は、ブロックチェーン アーキテクチャ、トランザクションの速度とコスト、スケーラビリティ、スマート コントラクト、ユースケース、時価総額、流通供給量が異なります。 Solana は高いスケーラビリティ、低い取引コスト、スマート コントラクトのサポートを備えていますが、ビットコインはそのセキュリティ、分散化、価値の保存としての特性で知られています。さまざまなニーズや好みに応じて、これら 2 つの暗号通貨はさまざまな市場のニーズに対応できます。

TikTokで親しい友達を追加するにはどうすればよいですか?親しい友達を追加するとどのようなメリットがありますか? TikTokで親しい友達を追加するにはどうすればよいですか?親しい友達を追加するとどのようなメリットがありますか? Apr 10, 2024 am 09:37 AM

Douyinの人気が高まるにつれ、プラットフォーム上で新しい友達を作り始める人が増えています。 Douyinに親しい友達機能が追加されたことで、ユーザー間の交流の可能性がさらに広がりました。では、TikTokで親しい友達を追加するにはどうすればよいでしょうか? 1.Douyinで親しい友達を追加するにはどうすればよいですか? 1. Douyin アプリを開き、ホームページに入り、右下隅の「Me」ボタンをクリックしてパーソナルセンターに入ります。 2. パーソナル センター ページで、[Douyin に親しい友達を追加] オプションを見つけてクリックして入力します。 3. 親しい友達の追加ページで、Douyin アカウント、携帯電話の連絡先、WeChat の友達などを検索して、必要な友達を追加できます。 4.追加したい友達のDouyinアカウントまたは携帯電話番号を入力し、検索ボタンをクリックします。 5. 検索結果には条件を満たす友達が表示され、親しい友達として追加することができます。 6.

See all articles