Java学习记录(12)

先写两题题解,就不多开一个页面了。

[NOIP1998 普及组] 三连击

题目背景

本题为提交答案题,您可以写程序或手算在本机上算出答案后,直接提交答案文本,也可提交答案生成程序。

题目描述

1 , 2 , … , 9 1, 2, \ldots , 9 1,2,,9 9 9 9 个数分成 3 3 3 组,分别组成 3 3 3 个三位数,且使这 3 3 3 个三位数构成 1 : 2 : 3 1 : 2 : 3 1:2:3 的比例,试求出所有满足条件的 3 3 3 个三位数。

输入格式

输出格式

若干行,每行 3 3 3 个数字。按照每行第 1 1 1 个数字升序排列。

样例 #1

样例输入 #1

样例输出 #1

192 384 576
* * *
...

* * *
(剩余部分不予展示)

开始我想着是从100遍历到999,还得设置特判,发现太麻烦了,就改成334了,没啥特别的思路,想明白就行。

#include <iostream>

using namespace std;

int cnt[11] = {0};
int Judge(int x)
{
    int ans;
    int ans2;
    int ans3;
    ans = x;
    ans2 = x * 2;
    ans3 = x * 3;
    int temp = ans;
    int temp2 = ans2;
    int temp3 = ans3;

    while(ans > 0)
    {
        cnt[ans % 10] ++;
        ans /= 10;
    }

    while(ans2 > 0)
    {
        cnt[ans2 % 10] ++;
        ans2 /= 10;
    }

    while(ans3 > 0)
    {
        cnt[ans3 % 10] ++;
        ans3 /= 10;
    }

    int flag = 0;
    for(int i = 1; i <= 9; i++)
    {
        if(cnt[i])
        {
            flag++;
            cnt[i] = 0;
        }
    }
    if(flag == 9)
        return 1;
    return 0;
}
int main()
{
    int i;
    
    for(i = 100; i < 334; i++)
    {
        if(Judge(i) == 1)
        cout << i  << " " << i * 2 <<" " << i * 3<< endl;
    }
    return 0;
}`

Dalton the Teacher

题目描述

Dalton is the teacher of a class with $ n $ students, numbered from $ 1 $ to $ n $ . The classroom contains $ n $ chairs, also numbered from $ 1 $ to $ n $ . Initially student $ i $ is seated on chair $ p_i $ . It is guaranteed that $ p_1,p_2,\dots, p_n $ is a permutation of length $ n $ .

A student is happy if his/her number is different from the number of his/her chair. In order to make all of his students happy, Dalton can repeatedly perform the following operation: choose two distinct students and swap their chairs. What is the minimum number of moves required to make all the students happy? One can show that, under the constraints of this problem, it is possible to make all the students happy with a finite number of moves.

A permutation of length $ n $ is an array consisting of $ n $ distinct integers from $ 1 $ to $ n $ in arbitrary order. For example, $ [2,3,1,5,4] $ is a permutation, but $ [1,2,2] $ is not a permutation ( $ 2 $ appears twice in the array), and $ [1,3,4] $ is also not a permutation ( $ n=3 $ but there is $ 4 $ in the array).

输入格式

Each test contains multiple test cases. The first line contains the number of test cases $ t $ ( $ 1 \le t \le 1000 $ ). The description of the test cases follows.

The first line contains a single integer $ n $ ( $ 2 \le n \le 10^5 $ ) — the number of students.

The second line contains $ n $ integers $ p_1, p_2, \ldots, p_n $ ( $ 1 \le p_i \le n $ ) — $ p_i $ denotes the initial chair of student $ i $ . It is guaranteed that $ p $ is a permutation.

It is guaranteed that the sum of $ n $ over all test cases does not exceed $ 10^5 $ .

输出格式

For each test case, output the minimum number of moves required.

样例 #1

样例输入 #1

5
2
2 1
3
1 2 3
5
1 2 5 4 3
4
1 2 4 3
10
10 2 1 3 6 5 4 7 9 8

样例输出 #1

0
2
2
1
1

提示

In the first test case, both students are already happy, so Dalton can perform $ 0 $ moves.

In the second test case, Dalton can swap the chairs of students $ 1 $ and $ 2 $ to get the array $ [2, 1, 3] $ . Then he can swap chairs of students $ 2 $ and $ 3 $ to get the array $ [2, 3, 1] $ . At this point all the students are happy, and he performed $ 2 $ moves. It is impossible to perform the task with fewer moves.

In the third test case, by swapping the chairs of students $ 1 $ and $ 2 $ and then swapping the chairs of students $ 4 $ and $ 5 $ , Dalton gets the array $ [2, 1, 5, 3, 4] $ in $ 2 $ moves.

然后这一题吧,大概意思就是数字不能与自己在数组中的位置所对应,所以要从1开始,全排列是没有零的。然后这题开始时想用贪心(说用最少的步数),后来想了一下,这题不就是找位置然后交换,那就比较好办了,你找到两个,就都换了,找到一个,那也得换一次,换一次不就是最少步数了吗,所以找到偶数,就是偶数个数除以二,奇数的话就要在偶数的基础上加1,就这样就完成了。

#include <iostream>

using namespace std;

int cnt[11] = {0};
int Judge(int x)
{
    int ans;
    int ans2;
    int ans3;
    ans = x;
    ans2 = x * 2;
    ans3 = x * 3;
    int temp = ans;
    int temp2 = ans2;
    int temp3 = ans3;

    while(ans > 0)
    {
        cnt[ans % 10] ++;
        ans /= 10;
    }

    while(ans2 > 0)
    {
        cnt[ans2 % 10] ++;
        ans2 /= 10;
    }

    while(ans3 > 0)
    {
        cnt[ans3 % 10] ++;
        ans3 /= 10;
    }

    int flag = 0;
    for(int i = 1; i <= 9; i++)
    {
        if(cnt[i])
        {
            flag++;
            cnt[i] = 0;
        }
    }
    if(flag == 9)
        return 1;
    return 0;
}
int main()
{
    int i;
    
    for(i = 100; i < 334; i++)
    {
        if(Judge(i) == 1)
        cout << i  << " " << i * 2 <<" " << i * 3<< endl;
    }
    return 0;
}

下面是项目的进展。项目呢是越写越多bug,所以得改。比如搜查好友,写完才发现要写好友不存在,然后写了不存在的查询,结果又发现了要正则判断输入的账号。。。

这里先插一句因为我的主界面没办法获取用户ID,所以最开始的user类不能拿来导入好友的资料数据,于是user类就变成了双份一样的内容。。。

package common;

import java.io.Serializable;

public class UserData implements Serializable {

    private static final long serialVersionUID = 1L;
    private String UserID;//用户ID
    private String Email;
    private String UserName;
    private String Sex;
    private String Birth;
    private String Age;
    private String Signature;
    private String Avatar;
    private String SearchId;
    private String SearchAvatar;
    private String SearchName;
    private String SearchSignature;
    private String SearchSex;
    private String SearchAge;
    private String SearchBirth;
    private int Relationship;

    public UserData(String userID, String email, String userName, String sex, String birth, String age, String signature, String avatar, String searchId, String searchAvatar, String searchName, String searchSignature, String searchSex, String searchAge, String searchBirth, int relationship) {
        UserID = userID;
        Email = email;
        UserName = userName;
        Sex = sex;
        Birth = birth;
        Age = age;
        Signature = signature;
        Avatar = avatar;
        SearchId = searchId;
        SearchAvatar = searchAvatar;
        SearchName = searchName;
        SearchSignature = searchSignature;
        SearchSex = searchSex;
        SearchAge = searchAge;
        SearchBirth = searchBirth;
        Relationship = relationship;
    }

    public String getSearchSignature() {
        return SearchSignature;
    }

    public void setSearchSignature(String searchSignature) {
        SearchSignature = searchSignature;
    }

    public String getSearchSex() {
        return SearchSex;
    }

    public void setSearchSex(String searchSex) {
        SearchSex = searchSex;
    }

    public String getSearchAge() {
        return SearchAge;
    }

    public void setSearchAge(String searchAge) {
        SearchAge = searchAge;
    }

    public String getSearchBirth() {
        return SearchBirth;
    }

    public void setSearchBirth(String searchBirth) {
        SearchBirth = searchBirth;
    }

    public String getSearchName() {
        return SearchName;
    }

    public void setSearchName(String searchName) {
        SearchName = searchName;
    }

    public String getSearchAvatar() {
        return SearchAvatar;
    }

    public void setSearchAvatar(String searchAvatar) {
        SearchAvatar = searchAvatar;
    }

    public int getRelationship() {
        return Relationship;
    }

    public void setRelationship(int relationship) {
        Relationship = relationship;
    }

    public UserData() {}


    public String getSearchId() {
        return SearchId;
    }

    public void setSearchId(String searchId) {
        SearchId = searchId;
    }

    public String getUserID() {
        return UserID;
    }

    public void setUserID(String userID) {
        UserID = userID;
    }

    public String getEmail() {
        return Email;
    }

    public void setEmail(String email) {
        Email = email;
    }

    public String getUserName() {
        return UserName;
    }

    public void setUserName(String userName) {
        UserName = userName;
    }

    public String getSex() {
        return Sex;
    }

    public void setSex(String sex) {
        Sex = sex;
    }

    public String getBirth() {
        return Birth;
    }

    public void setBirth(String birth) {
        Birth = birth;
    }

    public String getAge() {
        return Age;
    }

    public void setAge(String age) {
        Age = age;
    }

    public String getSignature() {
        return Signature;
    }

    public void setSignature(String signature) {
        Signature = signature;
    }

    public String getAvatar() {
        return Avatar;
    }

    public void setAvatar(String avatar) {
        Avatar = avatar;
    }
}

好麻烦,但是也好用,起码不会出错。

@FXML
    void SearchFriends(ActionEvent event) {
            user = UserNow.getUserNow();
            String UserId = GetFriendNum.getText();

            //这边记得加正则判断,然后要从得到的数据判断用户是否存在,也就是说从非主线程中生成一个警告语
            String regId = "^\\d{8,10}$";//这里判断有点问题
            Pattern patternId = Pattern.compile(regId);
            Matcher matcherId = patternId.matcher(UserId);
            if(UserId.length() == 0){
                Alert alert = new Alert(Alert.AlertType.INFORMATION);
                alert.setTitle("警告!");
                alert.setHeaderText(null);
                alert.setContentText("账号为空!");
                alert.showAndWait();
            }else{
                if(matcherId.find()){//正则判断
                    user.setSearchId(GetFriendNum.getText());
                    Client.AddFriend(user);
                }else
                {
                    Alert alert = new Alert(Alert.AlertType.INFORMATION);
                    alert.setTitle("警告!");
                    alert.setHeaderText(null);
                    alert.setContentText("请输入正确的账号形式!");
                    alert.showAndWait();
                }
            }
    }//用来搜索好友

这个就是搜寻好友的方法。然后在非主线程中生成页面要用platform方法,这里又卡了好久,用这个方法也是因为原先写的地方出错了(稍后介绍,其实不改也能跑而且还没那么多bug)。

 if(message.getMsgType().equals(MessageType.MESSAGE_SEARCH_FRIEND)){
                    UserData newUser =(UserData) message.getT();
                    Platform.runLater(() -> {
                        try {
                            System.out.println(newUser.getRelationship());
                            new UserNow().setUserNow(newUser);
                            if(newUser.getRelationship() == 9){
                                Alert alert = new Alert(Alert.AlertType.INFORMATION);
                                alert.setTitle("警告!");
                                alert.setHeaderText(null);
                                alert.setContentText("查无此人!");
                                newUser.setRelationship(0);
                                new UserNow().setUserNow(newUser);
                                alert.showAndWait();
                            }else{
                                if(CntFriend == 0){
                                    new StartLogin().showFriend(newUser);
                                    CntFriend++;
                                }else{
                                    new StartLogin().SHOWFRIEND(newUser);
                                }
                            }

                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    });

                }//查找好友且设置页面

这是platform方法,这样可以先在内存中实例化对象,再插入场景,做到对场景数据初始化处理。然后这里我用了个cnt计数,和先前写的是一样的,因为Parent根只能生成一次,多次生成会报错,然后开了一次页面后内存中就会记录下来,所以没办法做到重复生成Parent(我是这么理解的)。于是我想了下其他写法,就是第一次获取好友的时候生成一个Parent,第二次就跟先前写的更新数据一样,直接对按钮进行设置,然后也不需要再生成一个Scene,就完美解决了重复生成root的问题(也许并不完美,代码复用率太高了,我知道会挨骂)。

    public void showFriend(UserData userData){
        MainUser mainUser = loaderFriend.getController();
        Platform.runLater(() -> {
            // 创建JavaFX场景及其内容
            if(userData.getRelationship() != 9){
                mainUser.FriendName.setText(userData.getSearchName());
                mainUser.FriendAge.setText(userData.getSearchAge());
                mainUser.FriendId.setText(userData.getSearchId());
                mainUser.FriendSex.setText(userData.getSearchSex());
                mainUser.FriendSignature.setText(userData.getSearchSignature());
                mainUser.FriendBirth.setText(userData.getSearchBirth());
                if(userData.getAvatar() != null){
                    File imageFile = new File(userData.getSearchAvatar());
                    mainUser.FriendAvatar.setImage(new Image(imageFile.toURI().toString()));
                }
            Scene FriendScene = new Scene(FriendPage,360,290);
            stageFriend.setScene(FriendScene);
            stageFriend.setResizable(false);
            stageFriend.show();
            }
        });
    }

    public void SHOWFRIEND(UserData userData){
        MainUser mainUser = loaderFriend.getController();
        Platform.runLater(() -> {
            // 创建JavaFX场景及其内容
            if(userData.getRelationship() != 9){
                mainUser.FriendName.setText(userData.getSearchName());
                mainUser.FriendAge.setText(userData.getSearchAge());
                mainUser.FriendId.setText(userData.getSearchId());
                mainUser.FriendSex.setText(userData.getSearchSex());
                mainUser.FriendSignature.setText(userData.getSearchSignature());
                mainUser.FriendBirth.setText(userData.getSearchBirth());
                if(userData.getAvatar() != null){
                    File imageFile = new File(userData.getSearchAvatar());
                    mainUser.FriendAvatar.setImage(new Image(imageFile.toURI().toString()));
                }
            }
        });
        stageFriend.show();
    }

更新数据的方法我也写在下面:

public void SHOWMODIFYINFO(){
        stageModifyInfo.show();
    }

    public void FlushMainData(UserData userData){
        MainUser mainUser = loaderMain.getController();
        mainUser.VisibleSignature.setText(userData.getSignature());
        mainUser.VisibleUserName.setText(userData.getUserName());
        MainStage.show();
    }
    public void FlushData(UserData userData){
        MainUser mainUser = loaderInfo.getController();
        if(userData.getAvatar() != null)
        {
            File filePath = new File(userData.getAvatar());
            mainUser.VisibleAvatar.setImage(new Image(filePath.toURI().toString()));
        }
        mainUser.InformName.setText(userData.getUserName());
        mainUser.InforSignature.setText(userData.getSignature());
        mainUser.VisibleID.setText(userData.getUserID());
        mainUser.VisibleSex.setText(userData.getSex());
        mainUser.VisibleAge.setText(userData.getAge());
        mainUser.VisibleBirth.setText(userData.getBirth());
        stageInfo.show();
//        FlushMainData(userData);
    }

然后再说为什么是这么写。起因是前几天写无异常退出,发现移除socket之后客户端和服务端一起退了,然后我就很迷???明明是客户端退出而服务器要一直监听,后来通过查询资料才发现,如果登录成功以后,那个socket就要和UserID一起放进一个socket池中存储起来,再重写run方法使得该socket与客户端保持长连接,客户端那边也要这么操作,这样才能做到多线程通讯。不过改了两天其实还剩下挺多bug的,最经典的是如果提前登录了一个号,就没办法登录第二个号,然后修改过后还是没办法解决,如果同时登录两个账号就可以做到无异常退出和即时通讯。不过晚上给前辈展示的时候这个bug又莫名其妙的好了。。。不能理解。我最开始的写法是用单线程去写,其实也能写,不过越写到后面越难弄,比如获取该账号在线的socket就没办法了,于是迫不得已对代码进行了一番大改动。
现在的代码差不多就是下面这样:(这也是为什么我要用platform方法,这地方卡我挺久的)

public boolean checkUser(String UserId,String psd){

        boolean flag = false;//判断验证是否成功
        Connect();
        User user = new User();
        user.setUserID(UserId);
        user.setUserPsd(new MD5().Encrypt(psd));//设置对象
        ObjectOutputStream oos = null;
        try {
            Message ApplyLogin = new Message();
            ApplyLogin.setMsgType(MessageType.MESSAGE_APPLY_LOGIN);

            ApplyLogin.setT(user);
            oos = new ObjectOutputStream(socket.getOutputStream());
            oos.writeObject(ApplyLogin);//对象写入流
            //读取服务端回送的对象
            ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
            Message message = (Message) ois.readObject();//读取返回的Message对象判断是否成功
            if (message.getMsgType().equals(MessageType.MESSAGE_LOGIN_SUCCESS)) {
                flag = true;
                ManageThread manageThread = new ManageThread();
                ClientServerConnectThread clientServerConnectThread = new ClientServerConnectThread(socket);
                manageThread.addClientThread(user.getUserID(),clientServerConnectThread);
                clientServerConnectThread.start();//登录成功后拿到一个用户的socket并且与服务器保持长连接
            }else{
                socket.close();
            }

        }catch(Exception e){
            e.printStackTrace();
        }
        return flag;
    }//这里是登录验证

在上面是客户端发送了一个对象进服务器验证,成功后则将该对象和他的ID放入一个管理集合中(我用的是线程安全的hashmap),这样私聊的时候就可以直接通过ID拿取他的socket,然后直接用对象流给他传输消息,再将该消息存入数据库,这样的话可以加快接受消息的速度。

 public void run() {
        //因为要保持通讯,所以做一个死循环
        while (true) {
            try {
                ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
                Message message = (Message) ois.readObject();
                if (message.getMsgType().equals(MessageType.MESSAGE_USERDATA_ALL)) {
                    User userSet = (User) message.getT();
                    UserData userData = new UserData();
                    userData.setSignature(userSet.getSignature());
                    userData.setUserID(userSet.getUserID());
                    userData.setEmail(userSet.getEmail());
                    userData.setAge(userSet.getAge());
                    userData.setUserName(userSet.getUserName());
                    userData.setAvatar(userSet.getAvatar());
                    userData.setSex(userSet.getSex());
                    userData.setBirth(userSet.getBirth());

                    new UserNow().setUserNow(userData);
                    System.out.println("静态User已经设置");
                    Platform.runLater(() -> {
                        try {
                            new StartLogin().SetMainPage(userData);
                            new UserNow().setUserNow(userData);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        // 在这里写你想要在主线程中执行的代码
                    });
                 }//接收服务器返回的对象并设置页面

                if(message.getMsgType().equals(MessageType.MESSAGE_OK)){
                    continue;
                }

                if(message.getMsgType().equals(MessageType.MESSAGE_SEARCH_FRIEND)){
                    UserData newUser =(UserData) message.getT();
                    Platform.runLater(() -> {
                        try {
                            System.out.println(newUser.getRelationship());
                            new UserNow().setUserNow(newUser);
                            if(newUser.getRelationship() == 9){
                                Alert alert = new Alert(Alert.AlertType.INFORMATION);
                                alert.setTitle("警告!");
                                alert.setHeaderText(null);
                                alert.setContentText("查无此人!");
                                newUser.setRelationship(0);
                                new UserNow().setUserNow(newUser);
                                alert.showAndWait();
                            }else{
                                if(CntFriend == 0){
                                    new StartLogin().showFriend(newUser);
                                    CntFriend++;
                                }else{
                                    new StartLogin().SHOWFRIEND(newUser);
                                }
                            }

                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    });

                }//查找好友且设置页面
            } catch(Exception e){
                e.printStackTrace();
        }
    }
}

这里是重写run方法保持长连接。

package serverconnect;

import java.util.concurrent.ConcurrentHashMap;

public class ManageThread {
    //将线程放入Hashmap中形成线程池,key是用户ID,value就是线程
    private static ConcurrentHashMap<String,ClientServerConnectThread> hashMap = new ConcurrentHashMap<>();

    public static void addClientThread(String UserId,ClientServerConnectThread clientServerConnectThread){
        hashMap.put(UserId,clientServerConnectThread);
    }


    public static ClientServerConnectThread clientServerConnectThread(String UserId){
        return hashMap.get(UserId);
    }
}

管理线程的集合。

服务端也差不多与这个类似。

if(ChooseMes.getMsgType().equals(MessageType.MESSAGE_APPLY_LOGIN)){
                    try {
                        System.out.println("读入流对象创建成功");
                        User user = (User) ChooseMes.getT();
                        System.out.println("对象读入成功");
                        //接下来从数据库读取数据并验证
                        if(CheckLoginIDAndPsd(user.getUserID(),user.getUserPsd()))
                        {
                            System.out.println("账号密码验证成功");
                            ChooseMes.setMsgType(MessageType.MESSAGE_LOGIN_SUCCESS);
                            oos.writeObject(ChooseMes);
                            ServerConnectClientThread scct = new ServerConnectClientThread(socket, user.getUserID());
                            System.out.println("新登录用户" + user.getUserID());
                            new ManageClientThread().ThreadAdd(user.getUserID(),scct);
                            scct.start();
                        }else{
                            System.out.println("验证失败");
                            ChooseMes.setMsgType(MessageType.MESSAGE_LOGIN_FAILED);
                        }

                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }//这里是登录检查

登录成功后存储socket。

 @Override
    public void run() {
        System.out.println("进入run方法");
        Message ChooseMes;
        while (true){
            try {

                System.out.println("用户接口" + UserId +"持续监听");

                ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
                ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
                ChooseMes = (Message) ois.readObject();

                System.out.println("读取到的MESType:" + ChooseMes.getMsgType());
                if(ChooseMes.getMsgType().equals(MessageType.MESSAGE_USERDATA_ALL)){
                    User user = (User) ChooseMes.getT();
                    User Getuser = (User) new MySQLConnect().GetAlL(user);
                    ChooseMes.setMsgType(MessageType.MESSAGE_USERDATA_ALL);
                    ChooseMes.setT(Getuser);
                    oos.writeObject(ChooseMes);
                }//得到用户信息传回客户端

                if(ChooseMes.getMsgType().equals(MessageType.MESSAGE_USERDATA_AVATAR)){
                    UserData userData = (UserData) ChooseMes.getT();
                    User user = new User();
                    user.setAvatar(userData.getAvatar());
                    user.setUserID(userData.getUserID());
                    new MySQLConnect().SetAvatar(user.getAvatar(),user.getUserID());
                    ChooseMes.setMsgType(MessageType.MESSAGE_OK);
                    oos.writeObject(ChooseMes);
                }//上传用户头像

                if(ChooseMes.getMsgType().equals(MessageType.MESSAGE_MODIFY_USERDATA)){
                    User user = (User) ChooseMes.getT();
                    new MySQLConnect().SetAllDatas(user);//修改全部用户信息
                    ChooseMes.setMsgType(MessageType.MESSAGE_OK);
                    oos.writeObject(ChooseMes);
                }//更新数据库中所有的用户信息

                if(ChooseMes.getMsgType().equals(MessageType.MESSAGE_EXIT_SYSTEM)){
                    User user = (User) ChooseMes.getT();
                    System.out.println("要退出的用户为:" + user.getUserID());
                    ManageClientThread.removeServerConnectClientThread(user.getUserID());
                    socket.close();//关闭连接
                    break;
                }//无异常退出系统

                if(ChooseMes.getMsgType().equals(MessageType.MESSAGE_SEARCH_FRIEND)){
                    UserData user = (UserData) ChooseMes.getT();
                    UserData NewUser =(UserData) new MySQLConnect().GetFriend(user);
                    ChooseMes.setMsgType(MessageType.MESSAGE_SEARCH_FRIEND);
                    ChooseMes.setT(NewUser);
                    oos.writeObject(ChooseMes);
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

重写run方法保持监听。

package server;

import java.util.concurrent.ConcurrentHashMap;

public class ManageClientThread {
    private static ConcurrentHashMap<String,ServerConnectClientThread> hashMap = new ConcurrentHashMap<>();

    public void ThreadAdd(String UserId,ServerConnectClientThread serverConnectClientThread){
        hashMap.put(UserId,serverConnectClientThread);
    }

    public static ServerConnectClientThread serverConnectClientThread(String UserId){
        return hashMap.get(UserId);
    }

    public static void removeServerConnectClientThread(String ID){
        System.out.println("用户"+ID+"移除成功");
        hashMap.remove(ID);
    }
}

管理线程的集合。
私聊的实现暂时还没通过JavaFX文件,只用终端进行了测试,好友搜索应该是还有点问题,写完发现好像只写了搜索没写添加好友,得抓紧时间补齐。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值