1 集合框架
1去重排序
//LinkedHashMap 基于哈希表和双向链表的组合实现,因此它保持了插入顺序
//TreeMap 会根据键的自然顺序或者自定义的比较器对键进行排序(按升序排列)
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
ArrayList<String> list = new ArrayList<String>();
int n = cin.nextInt();
String s = cin.nextLine();
while(n -- != 0)
{
s = cin.nextLine();
if(list.contains(s))
continue;
list.add(s);
}
//属于匿名内部类 有一个new public返回int 名为compare
//转化为数字Integer.parseInt.取子串两个都是小写substring
list.sort(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return Integer.parseInt(o1.substring(0, 4)) - Integer.parseInt(o2.substring(0, 4));
//字符串转化为数字,从小到大排序
}
});
System.out.println(list.size());
for(String i:list)
System.out.println(i);
}
}
2定义
List<Girl> list = new ArrayList<Girl>();
Set<String> set = new LinkedHashSet<>()//输入顺序
Set<Integer> set1=new HashSet<>();//无序
Map<String, String> map = new LinkedHashMap<String, String>();//插入顺序
Map<String, String> map = new TreeMap<String, String>();//键升序,可以自动按照学号排序(String)
3比较器
list.sort(new Comparator<Girl>() {
@Override
public int compare(Girl o1, Girl o2) {
if(o1.hh == o2.hh)
return o2.age - o1.age;
return o1.hh - o2.hh;
}
});
//类中定义比较相等和输出函数分别返回boolean和string
@Override
public boolean equals(Object obj) {
Girl g = (Girl) obj;
if(hh!=g.hh)
return false;
if(age!=g.age)
return false;
if(!name.equals(g.name))
//字符串比较equals
return false;
if(!phone.equals(g.phone))
return false;
return true;
}
@Override
public String toString() {
return name + " " + hh + " " + age + " " + phone;
}
4函数
set1.containsAll(set2)
if(set1.containsAll(set2) && set2.containsAll(set1))
//判断集合相等
list.contains(s)
list.add(s);
s.equals("end")
5 map
//简化
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
Map<String, Integer> map = new TreeMap<String, Integer>();
while (true) {
String s = cin.next();
if (s.equals("end")) break;
map.put(s, map.getOrDefault(s, 0) + 1);
}
for (Map.Entry<String,Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + " " + entry.getValue());
//map输出
for(String it : map.keySet())
{
System.out.println(map.get(it));
}
}
}
}
import java.util.*;
import java.util.Map.Entry;
public class Main {
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
Map<String, Integer> map = new TreeMap<String, Integer>();
while(true)
{
String s = cin.next();
if(s.equals("end")) break;
map.put(s, map.getOrDefault(s, 0) + 1);
// Map 中的一个键值对(key-value pair)。它提供了访问 Map 中的每个元素的键
// (getKey()) 和值 (getValue()) 的方法
Iterator it = map.entrySet().iterator();
// entrySet() 方法返回一个包含所有键值对的集合
while(it.hasNext())
{
Entry ex = (Entry)it.next();
System.out.println(ex.getKey() + " " + ex.getValue());
}
}
}
6
import java.util.*;
class Student
{
String id, name, birth;
double score;
public Student(String id, String name, String birth, double score) {
this.id = id;
this.name = name;
this.birth = birth;
this.score = score;
}
@Override
public String toString() {
return "Student [" +
"id=" + id +
", name=" + name +
", birthday=" + birth +
", score=" + score +
']';
}
}
public class Main {
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
int n = cin.nextInt();
Map<String, Student> stu = new TreeMap<String, Student>();
for(int i = 0; i < n; i ++)
{
String id = cin.next();
String name = cin.next();
String birth = cin.next();
String[] temp = birth.split("-");
birth = temp[0] + "年" + temp[1] + "月" + temp[2] + "日";
double score = cin.nextDouble();
Student s = new Student(id, name, birth, score);
stu.put(id, s);
//把替代这个函数简化,因为对象不可比较treeset,所以用的map
}
for(String i:stu.keySet())
{
System.out.println(stu.get(i));
}
}
}
stu.put(id, s);
//遍历输出map
for(Map.Entry<String, Student> entry : stu.entrySet())
{
System.out.println(entry.getValue().toString());
}
7 计字器
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
Map<String, Integer> wordCount = new TreeMap<>();
//treemap自动排序
int[] charCount = new int[26]; // 只需要记录A-Z的字母
// 读取每行输入直到"0000"
while (true) {
String str = input.nextLine();
if (str.equals("0000")) break; // 结束条件
str = str.toUpperCase(); // 转换为大写字母
// 统计字符频次
for (int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
//记得要在a到z之间,不然可能统计标点空格
if (ch >= 'A' && ch <= 'Z') {
charCount[ch - 'A']++;
}
}
// 统计单词频次
String[] words = str.split("\\s+");
for (String word : words) {
wordCount.put(word, wordCount.getOrDefault(word, 0) + 1);
}
}
// 查找出现次数最多和最少的单词
String maxWord = "", minWord = "";
int maxCount = 0, minCount = 10000000;
for (String i : wordCount.keySet()) {
int count = wordCount.get(i);
if (count > =maxCount )
//大于0,则用字典序大的。
{
maxWord = i;
maxCount = count;
}
if (count < minCount) {
minWord = i;
minCount = count;
}
}
// 输出出现最多和最少的单词
System.out.printf("%-10s%8d\n", maxWord, maxCount);
System.out.printf("%-10s%8d\n", minWord, minCount);
//注意是printf不是print也不是println,同样后面无需%占位
// 输出每个字母出现的次数
/*for (char ch = 'A'; ch <= 'Z'; ch++) {
System.out.printf("%-10c%8d\n", ch, charCount[ch - 'A']);
}*/
for (int i = 0; i < 26; i++) {
System.out.printf("%-10s%8d\n", (char) (65 + i), charcou[i]);
}
//注意是(char)(65+i)
input.close();
}
}
8 购物车
import java.util.*;
class Shop {
public Shop(int id, String name1, String name2, double price, int save, int buy) {
this.id = id;
this.name1 = name1;
this.name2 = name2;
this.price = price;
this.save = save;
this.buy = buy;
}
int id;
String name1;
String name2;
double price;
int save;
int buy;
public String show1() {
return this.id + " " + this.name1 + " " + this.name2 + " " +String.format("%.2f",this.price)+ " " + this.save+" " + this.buy;
}
//化为二位小数String.format( )
public String show2() {
return this.id + " " + this.name1 + " " + this.name2 + " " + String.format("%.2f",this.price)+ " " + this.save;
}
}
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
ArrayList<Shop> shops = new ArrayList<>();
sc.nextLine();
//scnext不能吸收换行需要是nextline
for (int i = 0; i < n; i++) {
String[] s = sc.nextLine().split("\\s+");
shops.add(new Shop(Integer.parseInt(s[0]), s[1], s[2], Double.parseDouble(s[3]), Integer.parseInt(s[4]), 0));
}
int m = sc.nextInt();
for (int i = 0; i < m; i++) {
int id = sc.nextInt()-1;
//注意是id-1
int cou = sc.nextInt();
int sign = sc.nextInt();
Shop shop = shops.get(id);
if (sign == 1) {
int now = Math.min(cou, shop.save);
shop.buy += now;
shop.save -= now;
}
if (sign == 2) {
int now = Math.min(cou, shop.buy);
shop.buy -= now;
shop.save += now;
}
if (sign == 3) {
int now = shop.buy;
shop.buy -= now;
shop.save += now;
}
}
int t1 = 0;
int t2 = 0;
double sumprice = 0.0;
for (Shop shop1 : shops) {
if (shop1.buy != 0) {
t1++;
sumprice += shop1.buy * shop1.price;
}
}
System.out.println(t1);
for (Shop shop1 : shops) {
if (shop1.buy != 0) {
System.out.println(shop1.show1());
}
if (shop1.save != 0)
t2++;
}
System.out.printf("%.2f\n",sumprice);
System.out.println(t2);
for (Shop shop1 : shops) {
System.out.println(shop1.show2());
}
}
}
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
int n = cin.nextInt(); // 商品数量
cin.nextLine(); // 读取换行符
List<Shop> shops = new ArrayList<>();
// 读取商品信息
for (int i = 0; i < n; i++) {
String[] now = cin.nextLine().split("\\s+");
shops.add(new Shop(Integer.parseInt(now[0]), now[1], now[2], Double.parseDouble(now[3]), Integer.parseInt(now[4]), 0));
}
int m = cin.nextInt(); // 操作数量
while (m-- > 0) {
int x = cin.nextInt() - 1; // 商品索引
int y = cin.nextInt(); // 操作数量
int z = cin.nextInt(); // 操作类型
Shop shop = shops.get(x);
if (z == 1 && y > 0) { // 出售商品
int saleQuantity = Math.min(shop.save, y);
shop.save -= saleQuantity;
shop.buy += saleQuantity;
} else if (z == 2 && y > 0) { // 补充库存
int addQuantity = Math.min(shop.buy, y);
shop.save += addQuantity;
shop.buy -= addQuantity;
} else if (z == 3 && shop.buy > 0) { // 清空销售
shop.save += shop.buy;
shop.buy = 0;
}
}
// 输出有销售的商品
double totalSales = 0;
int count = 0;
for (Shop shop : shops) {
if (shop.buy > 0){
count++;
}
}
System.out.println(count);
for (Shop shop : shops) {
if (shop.buy > 0) {
System.out.println(shop.myshop());
totalSales += shop.price * shop.buy;
}
}
count=0;
System.out.printf("%.2f\n", totalSales);
System.out.println(shops.size());
for (Shop shop : shops) {
System.out.println(shop.show());
}
}
}
class Shop {
int id;
String name;
String store;
double price;
int save;
int buy;
public Shop(int id, String name, String store, double price, int save, int buy) {
this.id = id;
this.name = name;
this.store = store;
this.price = price;
this.save = save;
this.buy = buy;
}
public String myshop() {
return id + " " + name + " " + store + " " + String.format("%.2f", price) + " " + save + " " + buy;
}
public String show() {
return id + " " + name + " " + store + " " + String.format("%.2f", price) + " " + save;
}
}
2 IO流
1字节流处理所有文件
import java.io.*;
import java.util.*;
public class Main{
public static void main(String[] args) throws IOException {
Scanner sc=new Scanner(System.in);
FileOutputStream fos=new FileOutputStream("d:\\data.dat");
//文件输出流,我输出到文件。我->文件
String line=sc.nextLine();
while(!line.equals("end"))
{
fos.write((line).getBytes());
//字符串要转化为字节存入,直到输入为end
line=sc.nextLine();
}
fos.close();
//关闭输出流
StringBuffer buf=new StringBuffer();
//字符缓冲区
FileInputStream fis=new FileInputStream("d:\\data.dat");
//文件输入我。文件->我
byte[] bytes=new byte[10];
//字节数组,一次性最多能从文件里读取十个
int len=fis.read(bytes);
//读取字节数组实际长度,不是bytes.length而是read函数返回len。
while(len!=-1)
{
buf.append(new String(bytes,0,len));
//需要转为string而且需要new
len=fis.read(bytes);
}
fis.close();
//关闭输入流
System.out.println(buf);
//打出缓冲区
}
}
2字符流适用于txt文件
//参考代码1:利用FileReader和FileWriter对文件进行读写操作。
/*
字符流:适合用于文本文件的读写,因为它能够自动处理编码转换,适用于文本数据的读取和写入。
字节流:适合用于处理所有类型的文件(包括二进制文件),如图片、音频、视频等,或者当你需要完全控制字符编码时。
*/
import java.util.*;
import java.io.*;
public class Main{
public static void main(String[] args) throws IOException
//要抛出异常
{
Scanner sc=new Scanner(System.in);
FileWriter fw=new FileWriter("d:\\data.txt");
String line=sc.nextLine();
while(!line.equals("end")) {
fw.write(line);//这里不需要转化为byte
line = sc.nextLine();
}
fw.close();
//关闭输入输出流,必须在此处关闭,否则文件读入不会加载因为以为还没写完
FileReader fr=new FileReader("d:\\data.txt");
StringBuffer sb=new StringBuffer();
char[] chars=new char[10];
int len=fr.read(chars);
//将文件写入chars数组并返回数组的实际长度
while(len!=-1)
{
sb.append(new String(chars,0,len));
//记得写开始位置和结束位置,并且要转化为字符串,否则会出现乱码
//不管是字节还是字符都需要,newString 0-len
len=fr.read(chars);
}
fr.close();
System.out.println(sb);
}}
3 序列化和反序列化
import java.io.*;
import java.util.*;
class Student implements Serializable{ //接口Serializable可序列化
String id;
String name;
int age;
String clas;
public Student(String id, String name, int age, String clas) {
super();
this.id = id;
this.name = name;
this.age = age;
this.clas = clas;
}
public String toString() {
return "id:"+id+"\tname:"+name+"\tage:"+age+"\tclass:"+clas;
//制表符
}
}
public class Main {
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
//抛出异常
Student Array[]= {
new Student("001","xyl",19,"3"),
//用的是括号不是大括号,数组用大括号,构造器是括号
//记得构造方法,且用逗号分隔
new Student("002","smy",20,"3"),
new Student("003","zgl",18,"3")
};
// ObjectOutputStream 用于将对象写入到文件中。
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("stu.dat"));
//里面还有FileOutputStream;
oos.writeObject(Array);
// 将 Array 数组(即包含学生对象的数组)序列化并写入到 stu.dat 文件。
ObjectInputStream ois=new ObjectInputStream(new FileInputStream("stu.dat"));
// new FileInputStream("stu.dat") 创建一个文件输入流,用来从 stu.dat 文件中读取数据。
Object ob = ois.readObject();
// 读取文件中的对象,并将其反序列化为一个对象
if(ob instanceof Student[])
//只有一个对象,不用while,而且只有read一次就行
//instanceof不是一个方法,不是ob.instacne
//是学生数组类
{
Student list[]=(Student[])ob;
//显示转化直接写ob不行,而且没有new
for(Student stu:list)
{
System.out.println(stu);
}
}
oos.close();
ois.close();
}
}
4 其他
import java.io.*;
import java.net.*;
public class Main {
public static void main(String[] args) throws IOException {
URL u=new URL("https://www.sdut.edu.cn/");
InputStream is=u.openStream();
//记得这个openstream,只有写入文件里,不用才文件里读取
OutputStream os=new FileOutputStream("d:/sdut.html");
byte byes[]=new byte[10];
int len=0;
while((len=is.read(byes))!=-1)
{
os.write(byes, 0, len);
//写入写的是字节不=所以不用newstring
}
}
}
//利用File类进行文件及文件夹名称的显示
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException, ClassNotFoundException {
File file=new File("d:/test");
File[] l = file.listFiles();
//返回file数组,可以获得文件的各种详细信息
if(l==null)
{
System.out.println("不存在");
}
else
{
for(int i=0;i<l.length;i++)
System.out.println(l[i]);
System.out.println("------所有文本文件如下------");
String[] l2 = file.list();
//返回string数组,只返回文件名
for(int i=0;i<l2.length;i++)
{
if(l2[i].endsWith(".txt"))
System.out.println(l2[i]);
}
}
}
}
//利用字节输入输出流(或字符输入输出流)类,读入数据-输出文件-读入文件-显示数据
import java.io.*;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws IOException {
Scanner reader=new Scanner(System.in); //准备从键盘读取数据
String line = reader.nextLine();//读取一行
FileWriter fw=new FileWriter("d:\\data\\myfile.txt"); //创建文件输出流
//若读取到的一行字符串不为“end",写文件
while(!line.equals("end"))
{
fw.write(line); //写文件
line=reader.nextLine(); //从键盘再读一行字符
}
fw.close(); //输出流关闭
StringBuffer buf=new StringBuffer(); //创建字符串缓冲区
FileReader fr=new FileReader("d:\\data\\myfile.txt"); //创建文件输出流
char[] chars=new char[10];
int len=fr.read(chars); //第一次读文件
//若文件尚未读取结束,则边读边显示数据
while(len!=-1)
{
String str=new String(chars,0,len); //由字节数组构造字符串,便于观察
buf.append(str);
len=fr.read(chars); //再读一次文件
}
fr.close(); //文件输入流关闭
System.out.println(buf);
}
}
3 多线程
Runnable 接口定义线程要执行的任务,Runnable 接口提供了一个 run() 方法。
Thread.currentThread().getName()
//利用runnable创建线程
class myrun implements Runnable
{
int value;
myrun(int value)
{
this.value=value;
}
public void run(){
for(int i=0;i<20;i++)
{
System.out.println(value);
value+=2;
}
}
}
public class Main{
public static void main(String[] args)
{
myrun m1=new myrun(0);
myrun m2=new myrun(1);
Thread t1=new Thread(m1);
Thread t2=new Thread(m2);
t1.start();
t2.start();
}
}
class MyRunnable implements Runnable{
// 通过实现 Runnable 接口,
// 任务代码与线程的创建和启动代码分离开。这样,任务可以独立于线程对象,被多个线程共享执行。
//Runnable 是一个接口,支持多实现,
// 可以将同一个任务传递给多个线程对象。不同线程可以共享同一个 Runnable 实现,
int num=10;
public void run(){
while(true){
if(num==0)
break;
System.out.println(Thread.currentThread().getName()+"卖出第"+num--+"张票");
//记得要获得窗口名
}
}
}
public class Main{
public static void main(String[] args){
MyRunnable m1=new MyRunnable();
// 将 Runnable 对象传递给不同的线程实例,从而让多个线程执行同一个任务。
Thread t1=new Thread(m1,"窗口1");
//线程执行的任务,线程名称,先任务后线程名
Thread t2=new Thread(m1,"窗口2");
Thread t3=new Thread(m1,"窗口3");
/*
start() 方法是 Thread 类的方法。
当你调用 start() 时,线程并不会立刻执行 run() 方法,
而是将线程加入到线程调度队列,等待 JVM 调度执行。它用于启动一个新线程,内部会调用 run() 方法来执行线程任务
*/
t1.start();
t2.start();
t3.start();
}
}
public class NumberThread extends Thread{
// NumberThread 类继承了 Thread 类。每个 Thread 对象代表一个单独的线程
int value;
public NumberThread(int value) {
super();
this.value = value;
}
@Override
public void run() {
for(int i=0;i<20;i++)
{
System.out.print(value+" ");
value+=2;
//输出20个偶数和20个奇数
//线程是轮流交替执行的
}
}
}
public class Main{
public static void main(String[] args) {
NumberThread nt=new NumberThread(0);
NumberThread nt1=new NumberThread(1);
nt.start();
nt1.start();
//要用start不是run,start加入任务行列等待执行才是多线程
}
}
4 网络编程
tcp
import java.io.*;
import java.net.*;
import java.util.*;
public class Main {
//客户端
public static void main(String[] args) throws IOException {
//抛出io异常
// 创建一个 Scanner 对象来读取用户输入
Scanner cin = new Scanner(System.in);
// 使用 InetAddress 创建一个本地的 IP 地址 127.0.0.1
//InetAddress.getByAddress(byte[] addr)是该类的构造方法
// 必须使用 new 关键字显式创建数组,或者通过变量传递一个数组
InetAddress ip = InetAddress.getByAddress(new byte[]{127, 0, 0, 1});
// 创建一个 Socket,连接到服务器,服务器的地址是 127.0.0.1(localhost),端口号是 8888
Socket socket = new Socket(ip, 8888);
//客户端发起连接请求
// Socket 是 Java 中用于网络通信的类,它允许客户端与服务器之间建立连接并进行数据交换。
// 获取 socket 的输出流,用于发送数据
OutputStream os = socket.getOutputStream();
// 读取控制台输入的字符串并发送给服务器
String line = cin.nextLine();
os.write(line.getBytes()); // 将字符串转换为字节并发送
// 关闭输出流,表示客户端发送完数据
socket.shutdownOutput();
// 获取 socket 的输入流
// 获取输入流,接收服务器返回的数据并将其打印出来
InputStream is = socket.getInputStream();
int len = 0;
byte[] bytes = new byte[10]; // 用于读取数据的缓冲区
StringBuffer buffer = new StringBuffer(); // 用于存储接收到的数据
// 读取服务器返回的数据
while ((len = is.read(bytes)) != -1) {
buffer.append(new String(bytes, 0, len)); // 将读取到的数据拼接到 buffer
}
// 打印服务器返回的数据
System.out.println("Client has received:" + buffer.toString());
// 关闭输入流、输出流和 Socket
is.close();
os.close();
socket.close();
}
}
import java.io.*;
import java.net.*;
import java.util.*;
public class Main {
//服务端
public static void main(String[] args) throws IOException {
// 创建一个 ServerSocket,监听端口 8888
ServerSocket ss = new ServerSocket(8888);
//通过888ss获取socket
// 无限循环,接受来自客户端的连接
while (true) {
// 等待客户端连接,返回一个 Socket 对象
Socket socket = ss.accept();
//是accept
// 获取输入流,读取客户端发送的数据
InputStream is = socket.getInputStream();
byte[] bytes = new byte[10]; // 缓冲区,用于读取数据
int len = 0;//int是小写
StringBuffer buffer = new StringBuffer(); // 用于拼接读取到的数据
// 读取客户端的数据
//读入输入流并且填入bytes数组,如果没有输入流返回-1
while ((len = is.read(bytes)) != -1) {
buffer.append(new String(bytes, 0, len));
//记得要加String
}
// 打印客户端发送的数据
System.out.println("I have receive " + buffer.toString());
// 获取输出流,准备给客户端发送响应
OutputStream os = socket.getOutputStream();
os.write(("Message from Server is:" + buffer.toString()).getBytes());
//buffer->string 用tostring
// 不管有没有end,一个输入结束,先关闭输入流关闭输入流、输出流和 Socket
is.close();
os.close();
socket.close();
// 如果客户端发送的消息是 "end",则服务器停止服务,记得转化string
if ("end".equals(buffer.toString())) {
break;
}
//break的作用
}
// 关闭 ServerSocket,这个是在while循环外头
ss.close();
}
}
2 upd
import java.net.*;
import java.util.*;
import java.io.*;
public class Main {
//客户端打印输入的数据,发送数据给服务端,打印服务端返回的数据
public static void main(String[] args) throws IOException {
Scanner cin = new Scanner(System.in); // 创建一个Scanner对象,用于从控制台读取输入
DatagramSocket ds = new DatagramSocket(); // 创建一个DatagramSocket对象,用于发送UDP数据包
String line = cin.nextLine(); // 从控制台读取一行字符串输入
// 创建一个DatagramPacket对象,用于发送数据
DatagramPacket dp = new DatagramPacket(
line.getBytes(), // 数据内容,将输入字符串转换为字节数组
line.length(), // 数据长度
InetAddress.getByAddress(new byte[]{127, 0, 0, 1}), // 目标地址,127.0.0.1 是本机地址
9999 // 目标端口,UDP协议通常没有连接的概念,所以可以直接指定目标的IP地址和端口
);
ds.send(dp); // 发送数据包
byte[] bytes = new byte[1024]; // 创建一个字节数组,用来接收数据,注意是1024
DatagramPacket dp1 = new DatagramPacket(bytes, bytes.length); // 创建一个DatagramPacket接收数据
ds.receive(dp1); // 接收数据包
byte[] data = dp1.getData(); // 获取数据包中的数据
int len = dp1.getLength(); // 获取数据的长度
System.out.println("Client has received: "); // 输出接收到的数据
System.out.println(new String(data, 0, len)); // 将字节数组转换为字符串并打印出来
ds.close(); // 关闭DatagramSocket对象
}
}
import java.io.*;
import java.net.*;
public class Main {
//服务端接受数据,返回数据,打印返回的数据
public static void main(String[] args) throws IOException {
DatagramSocket ds = new DatagramSocket(9999); // 创建一个DatagramSocket对象,绑定到端口9999
while(true) {
byte[] bytes = new byte[1024]; // 创建一个字节数组,接收客户端的数据
DatagramPacket dp = new DatagramPacket(bytes, bytes.length); // 创建一个DatagramPacket来接收数据
ds.receive(dp); // 接收数据包
byte[] data = dp.getData(); // 获取接收到的数据
String str = new String(data, 0, dp.getLength()); // 将字节数组转换为字符串
System.out.println("I have received: " + str); // 打印接收到的数据
// 构造响应数据
byte[] dataout = ("Message from Server is: " + str).getBytes();
DatagramPacket dp1 = new DatagramPacket(dataout, dataout.length, dp.getAddress(), dp.getPort());
//不能改成客户端那样
ds.send(dp1); // 发送数据包回客户端
if ("end".equals(str)) // 如果收到的消息是 "end",则退出循环
break;
}
ds.close(); // 关闭DatagramSocket连接
}
}
5 论述
1 方法重载和方法覆盖,代码复用
//方法重载是指同一个类中定义多个方法,这些方法具有相同的名称,但参数列表不同(参数的数量、类型或者顺序不同
//方法覆盖是指子类重新实现父类中的方法。方法的签名相同,但实现不同
//方法重写和方法覆盖是一个概念,需要用@Override
class Animal {
public void state(){
System.out.println("这是一只动物");
}
public void shout() {
System.out.println("动物叫");
}
}
//不是公共类,只能有一个公共类Main
class Dog extends Animal {
@Override
public void shout() {
System.out.println("汪汪叫");
}
public int add(int a) {
return a + 1;
}
public int add(int a, int b) {
return a + b + 2;
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog();
Animal animal=new Animal();
dog.state();//代码复用
animal.shout();
dog.shout();
//方法覆盖
System.out.println(dog.add(1)+" "+dog.add(1,2));
//方法重载
}
}
2 封装
私有化属性:name 是 private,外部无法直接访问它。
提供公共方法:setName() 和 getName() 提供了对 name 属性的安全访问。
class Animal {
public void state(){
System.out.println("这是一只动物");
}
public void shout() {
System.out.println("动物叫");
}
}
//不是公共类,只能有一个公共类Main
class Dog extends Animal {
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void shout() {
System.out.println("汪汪叫");
}
public int add(int a) {
return a + 1;
}
public int add(int a, int b) {
return a + b + 2;
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog();
dog.setName("旺财");
Animal animal=new Animal();
dog.state();
animal.shout();
dog.shout();
System.out.println(dog.getName()+dog.add(1)+" "+dog.add(1,2));
}
}
3 抽象类和接口
/*
接口:
1,需要支持多重继承/多重实现:
当一个类需要继承多个不相关的行为时,接口是一个理想的选择。Java 允许一个类实现多个接口,而不像抽象类只能单继承。
2,同类的行为共享:
当你希望多个类实现同一行为,但这些类之间并不需要共享实现细节时,接口更合适。接口仅定义方法签名和行为约定,而不关心具体实现。
3,
接口作为抽象的行为规范:
当你想定义一个可以被多个类“实现”的功能时,
抽象类:
1,需要共享实现代码:
当多个类之间有相同的功能或数据时,可以使用抽象类来共享代码。抽象类可以包含一些已实现的方法,这样子类只需实现抽象方法,而不必重复写相同的代码
有共同的父类功能/属性:
2,
如果多个类有共同的属性或行为,抽象类可以作为它们的共同父类。通过继承抽象类,子类可以复用父类的字段和方法,避免重复代码。
子类之间有“是一个”的关系:
如果你想表达类之间的继承关系,并且希望子类继承父类的某些属性或方法,抽象类更为适合。例如,“动物”是一个类,“狗”和“猫”是“动物”的子类,它们共享一些基本属性和行为。
当你想定义一个可以被多个类“实现”的功能时,接口是合适的选择。
接口强调的是类必须提供某种行为,而不关心如何实现。
当多个类之间有相同的功能或数据时,可以使用抽象类来共享代码。
抽象类可以包含一些已实现的方法,这样子类只需实现抽象方法,而不必重复写相同的代码。
*/
1
/*
接口支持多继承,一个类可以继承多个接口,类可以通过接口实现多个功能,接口更灵活。
接口里的方法默认为public,成员变量为常量。
抽象类不支持多重继承,一个类只能继承一个抽象类。
抽象类可以包含已实现的方法和抽象方法,可以使用private等访问修饰符修饰成员变量
继承抽象类的子类必须实现抽象类的所有抽象方法。
多个类之间有很多共同实现用抽象类,
需要为类提供好多不同功能,希望多个类实现同一行为,用接口
*/
import java.util.*;
abstract class Animals {
// 抽象方法
abstract void shout();
abstract void swim();
}
class Dog extends Animals {
// 实现抽象方法 shout
void shout() {
System.out.println("wang");
}
// 实现抽象方法 swim
void swim() {
System.out.println("狗擅长游泳");
}
}
class Cat extends Animals {
// 实现抽象方法 shout
void shout() {
System.out.println("miao");
}
// 实现抽象方法 swim
void swim() {
System.out.println("猫不擅长游泳");
}
}
public class Main {
public static void main(String[] args) {
// 创建 Dog 和 Cat 对象
Dog dog = new Dog();
Animals cat = new Cat();
// 调用 Dog 对象的方法
dog.shout(); // 输出: wang
dog.swim(); // 输出: 狗擅长游泳
// 调用 Cat 对象的方法
cat.shout(); // 输出: miao
cat.swim(); // 输出: 猫不擅长游泳
}
}
2定义方式,实现方式,应用场景
1,定义方式
抽象类使用 abstract 关键字声明
接口使用 interface 关键字声明
2,实现方式
类可以继承一个抽象类,并且必须实现该抽象类的所有抽象方法(除非该类本身也被声明为抽象类)。
一个类只能继承一个抽象类(Java不支持多重继承)。
类通过 implements 关键字实现接口,必须实现接口中的所有抽象方法(除非该类是抽象类)
3,应用场景
多个类之间有很多共同实现用抽象类,
需要为类提供好多不同功能,希望多个类实现同一行为,用接口
import java.util.*;
abstract class Animals {
// 抽象方法
abstract void shout();
abstract void swim();
}
interface eat{
void eatwhat();
}
class Dog extends Animals implements eat{
// 实现抽象方法 shout
public void shout() {
System.out.println("wang");
}
// 实现抽象方法 swim
public void swim() {
System.out.println("狗擅长游泳");
}
public void eatwhat(){
System.out.println("狗吃骨头");
}
}
class Cat extends Animals implements eat{
// 实现抽象方法 shout
void shout() {
System.out.println("miao");
}
// 实现抽象方法 swim
void swim() {
System.out.println("猫不擅长游泳");
}
public void eatwhat(){
System.out.println("猫吃鱼");
}
}
public class Main {
public static void main(String[] args) {
// 创建 Dog 和 Cat 对象
Dog dog = new Dog();
Animals cat = new Cat();
// 调用 Dog 对象的方法
dog.shout(); // 输出: wang
dog.swim(); // 输出: 狗擅长游泳
dog.eatwhat();
// 调用 Cat 对象的方法
cat.shout(); // 输出: miao
cat.swim(); // 输出: 猫不擅长游泳
}
}
4 自转和强转
自动类型转换:转换发生在较小的数值类型转换为较大的数值类型,或者从子类类型转换为父类类型(从 int 到 long
自动进行,不需要开发者显式地干预,一般不会丢失精度。
强制类型转换是指将一个较大类型的数据强制转换为较小类型的数据(可能会丢失数据),或者将父类类型转换为子类类型。
需要显式指定转换,可能会丢失数据或导致运行时异常,可能会发生 ClassCastException 错误。
public class Main{
public static void main(String[] args) {
//自动转换
int num = 99;
double doublenum = num;
System.out.println(doublenum);
//强制转换
double n2=99.1;
int intn2=(int)n2;
System.out.println(intn2);
}
}
5 字符,字符缓冲,日期相互转化
import java.text.*;
import java.util.*;
public class Main{
public static void main(String[] args) throws Exception
//要抛出异常
{
//基本数据类型->String
double num1=99.1;
String numstr1=String.valueOf(num1);
//String->基本数据类型
String numstr2="99.2";
double num2=Double.parseDouble(numstr2);
//String->StringBuffer
String str="hello";
StringBuffer bf = new StringBuffer(str);
//StringBuffer->String
StringBuffer bf2=new StringBuffer("hello");
String str2=bf2.toString();
//String->Date
String str3="2024-12-15";
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
//要大写M,小写m表示分钟
Date date=sdf.parse(str3);
//Date->String
Date currentDate=new Date();
SimpleDateFormat sdf2=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//大写HH,大写MM;
String datestr=sdf.format(currentDate);
}
}
6 set,map,list的特点
List:需要按顺序存储并可能有重复元素的场景。(电影评分)
Set:不允许重复元素且不关心顺序的场景(观看电影观众姓名)
Map:需要键值对映射的场景(电影和电影票价格)
import java.util.*;
public class Main{
public static void main(String[] args)
{
ArrayList<Double> list=new ArrayList();
HashSet<String> set=new HashSet();
HashMap<String,Integer> map=new HashMap();
list.add(8.1);
list.add(9.2);
list.add(6.0);
Collections.sort(list);//double的排序
set.add("xiaoming");
set.add("xiaohong");
map.put("2D电影",50);
map.put("3D电影",80);
}
}
7 c和java的区别,面对对象和面向过程
1区别
内存,指针,面向对象
C语言:C语言提供了直接的内存管理机制,程序员可以使用 malloc 和 free 来分配和释放内存。
Java语言:Java使用自动垃圾回收机制,开发者无需显式地分配和释放内存,Java虚拟机会在后台自动管理内存.
C语言:C语言允许使用指针,开发者可以通过指针访问和操作内存地址
Java语言:Java不支持显式的指针操作,所有的对象引用通过引用变量来访问
C语言是一种面向过程的编程语言,程序是通过一系列函数(过程)进行组织的.
Java是一种面向对象的编程语言,程序由对象和类组成。Java强调封装、继承和多态.
2 oop
面向对象的核心概念是 类和对象,封装,继承,多态
1,面向对象编程将代码分割为多个独立的对象,每个对象封装了特定的功能和数据,具有更高的模块化
2,面向对象编程,便于程序的维护和扩展。当需要修改或增加功能时,只需修改或增加相关的对象,