廖雪峰PythonJava对比学习1

廖雪峰PythonJava对比学习1

语言类型

1
java是javac编译器先编译成字节码.class文件,后java虚拟机解释生成机器码执行
1
2
3
intellij idea使用python

https://www.oryoy.com/news/intellij-idea-pei-zhi-python-kai-fa-huan-jing-cong-an-zhuang-dao-diao-shi-quan-zhi-nan.html
1
2
静态语言java
动态语言python

输入和输出

python

1
python里输入input,输出print

java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
java里输入:
import java.util.Scanner;

public class test {
public static void main(String[] args) {
Scanner input = new Scanner(System.in); // 创建 Scanner 对象
System.out.print("请输入字符串: ");
String s; // 读取用户输入的整数
while(input.hasNextLine()){
s = input.nextLine();
System.out.println("您输入的字符串是: " + s);
}

}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import java.util.Scanner;

public class test {
public static void main(String[] args) {
Scanner input = new Scanner(System.in); // 创建 Scanner 对象
System.out.print("请输入一个整数: ");
int number; // 读取用户输入的整数
while(input.hasNextInt()){
number = input.nextInt();
System.out.println("您输入的整数是: " + number);
}

}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import java.util.Scanner;

public class test {
public static void main(String[] args) {
Scanner input = new Scanner(System.in); // 创建 Scanner 对象
System.out.print("请输入字符串: ");
String s; // 读取用户输入的整数
while(input.hasNext()){
s = input.next();
System.out.println("您输入的字符串是: " + s);
}

}
}
1
2
3
4
nextFloat()
hasNextFloat()
nextDouble
hasNextDouble

数据类型

1
java中除了整型,浮点型,布尔,字符型以外都是引用类型

字符串

1
2
3
4
5
6
7
用单引号或者双引号都可以表示字符串(java中字符用单引号,字符串用双引号)

换行字符串(如果字符串内部有很多换行,用\n写在一行里不好阅读)(和java一样):
'''
xxx
xxx
'''

字符串转义

1
2
3
4
字符串转义:
\(同java)
r'''xxx'''
r''表示''内部的字符串默认不转义

字符串格式化

1
2
3
4
5
6
7
8
9
字符串格式化:
s="%s %0d %.2f"%(x,x,x)
s="{0}xx{1}".format(1,22)
v1=10
v2=20
s=f'xxx{v1}xx{v2}'

java中:
String.format("xxx%sxxx %d","aa",20)

字符串连接

1
2
3
4
5
6
7
8
9
字符串连接:
+(同java)
字符串格式化方式(同java)
sql:concat,concat_ws,group_concat

string类型join方式连接list/tuple类型:
words = ["Hello", "World"]
result = " ".join(words) # 前面引号内是连接符
print(result) # 输出: Hello World
1
2
3
4
5
6
7
java中高效的方式:
StringBuilder sb = new StringBuilder(1024);
for(int i=0;i<1000;i++){
sb.append(',');
sb.append(i);
}
String s = sb.toString();

字符串替换

1
2
>>> a = 'abc'
>>> a.replace('a', 'A')(同java) // 其中所有匹配的字符或子字符串都被替换
1
2
3
4
java中还有这个方法:
String str = "Hello 123 World";
String newStr = str.replaceAll("[0-9]+", ""); // 移除所有数字
System.out.println(newStr); // 输出:Hello World
1
sql有个replace函数

整数

1
python里整型浮点数可以表示无限大

空值

1
空值None(java中null,同sql)

常量

1
2
python里默认用全大写的英文名字表示常量但是还是可以改变它的值:PI=3.14..
java用final修饰

列表

1
list:有序集合列表 里面可以是不同的数据类型 insert(index,v) append(v) pop() pop(5) .sort()

LIST ARRAYLIST LINKEDLIST

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
java中有对应的叫array数组,但是这个是一个很基本的东西,删除和添加元素时需要自己移动元素,普通数组一旦定义就不能更改长度

list接口的一个实现类arraylist是一个比较高级的东西,封装了删除和添加方法,内部还是arraylist

add()可以添加到最后面,也可以到指定为止(同python list的insert方法)
remove() 可以删除指定元素,也可以根据下标删除(类似python的pop方法)
get()
indexOf(x)
contain(x)
size()

list接口还有一个linkedlist实现类

list遍历可以用while循环生成下标,用get获取,但是这种方法在用到linkedlist上时效率很低
for (int i=0; i<list.size(); i++) {
String s = list.get(i);

通过Iterator遍历List永远是最高效的方式 下面这种写法也比较复杂
for (Iterator<String> it = list.iterator(); it.hasNext(); ) {
String s = it.next();

Java的for each循环本身就可以帮我们使用Iterator遍历
for (String s : list) {
System.out.println(s);

支持用这种方式创建list(是一种只可读的list)
List<Integer> list = List.of(1, 2, 5);
List.of()方法不接受null值,如果传入null,会抛出NullPointerException异常

// array和list相互转化
Integer[] array = { 1, 2, 3 };
List<Integer> list = List.of(array); 是一种只可读的list)

equals()

1
2
3
要能够使用contain(),indexof(x)等这些方法,传入的元素需要正确编写equals()方法

之所以能正常放入String、Integer这些对象,是因为Java标准库定义的这些类已经正确实现了equals()方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
对于引用字段比较,我们使用equals(),对于基本类型字段的比较,我们使用==

public boolean equals(Object o) {
if (o instanceof Person p) {
boolean nameEquals = false;
if (this.name == null && p.name == null) {
nameEquals = true;
}
if (this.name != null) {
nameEquals = this.name.equals(p.name);
}
return nameEquals && this.age == p.age;
}
return false;
}

如果Person有好几个引用类型的字段,上面的写法就太复杂了。要简化引用类型的比较,我们使用Objects.equals()静态方法:
public boolean equals(Object o) {
if (o instanceof Person p) {
return Objects.equals(this.name, p.name) && this.age == p.age;
}
return false;
}

元组

1
tuple:有序不可改变集合元组,存储的元素为列表时列表里的数据可以改变的,只是指向不变

集合

1
2
3
4
5
set和dict差不多:无序,不重复(dict的key不重复)(可以用它去重)
set.add(xx) .remove(xx)

s = {1, 2, 3}
s = set([1, 2, 3])
1
2
3
4
5
6
7
8
9
10
11
12
13
14
java中有set,常用的实现类是hashset底层使用了hashmap

同python的set一样不会重复,也无序(hashset继承set,有序的sortedset继承set,treeset继承sortedset)

放入Set的元素和Map的key类似,都要正确实现equals()和hashCode()方法,否则该元素无法正确地放入Set

Set<String> set = new HashSet<>();
System.out.println(set.add("abc")); // true
System.out.println(set.add("xyz")); // true
System.out.println(set.add("xyz")); // false,添加失败,因为元素已存在
System.out.println(set.contains("xyz")); // true,元素存在
System.out.println(set.contains("XYZ")); // false,元素不存在
System.out.println(set.remove("hello")); // false,删除失败,因为元素不存在
System.out.println(set.size()); // 2,一共两个元素

hashset

treeset

Queue

1
LinkedList即实现了List接口,又实现了Queue接口

PriorityQueue

1
需要对元素实现comparable接口重写compareTo方法,或者传入的Comparator实现compare方法

Deque

1
2
3
4
5
允许两头都进,两头都出,这种队列叫双端队列

Deque<String> d2 = new LinkedList<>();

LinkedList是一个全能选手,它即是List,又是Queue,还是Deque。但是我们在使用的时候,总是用特定的接口来引用它

Stack

1
2
Stack只有入栈和出栈的操作
在Java中,我们用Deque可以实现Stack的功能

tostring

1
2
3
4
5
6
7
8
9
10
11
让print知道如何打印一个自定义对象

class Person {
public String name;
Person(String name) {
this.name = name;
}
public String toString() {
return "{Person: " + name + "}";
}
}
1
python里叫__str__()方法

字典

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
dict['xx']和dict.get('xx'):前者没有key值时报错后者返回None

可以用in判断是否有对应key

d.get('Thomas', -1) #没有时返回-1

dict.pop('xx')

遍历key:
for key in mydict.keys(): # 这里不写keys()也可以

遍历value:
for v in mydict.values():

同时遍历key,value
for key,value in mydict.items():

MAP HASHMAP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
java中也有类似的map接口,常用的实现类是hashmap

Student s = new Student("Xiao Ming", 99);
Map<String, Student> map = new HashMap<>();
map.put("Xiao Ming", s); // 将"Xiao Ming"和Student实例映射并关联
Student target = map.get("Xiao Ming");

get方法获取不到对应的key时返回null

可以调用boolean containsKey(K key)方法判断是否有对应的键

和python一样对同一个key存入value是会覆盖

遍历key:
for (String key : map.keySet()) {
Integer value = map.get(key);

同时遍历key和value:
for (Map.Entry<String, Integer> entry : map.entrySet()) {
String key = entry.getKey();
Integer value = entry.getValue();
1
2
3
4
5
6
hashmap底层使用了数组来存储key-value,对key使用hashcode将值存储在对应的位置上,当不同的key计算hash值后相同,这就叫hash冲突(会用数组来存储相同的映射值)

hashmap底层默认的数组的大小是很小的,当存储满了时会自动扩容,但是扩容这个过程会对之前所有的key-value从新计算hash值,然后重新存放
,为了避免这个过程,可以在创建hashmap时指定大小

Map<String, Integer> map = new HashMap<>(10000);

hashCode()

1
要能正确使用map,key需要实现equals方法,value需要实现hashcoe方法

EnumMap

1
key的对象是enum类型

TreeMap

1
2
3
4
5
有序的map,保证遍历顺序和存入的顺序一样

未覆写equals()和hashCode(),因为TreeMap不使用equals()和hashCode()

Key必须实现Comparable接口,或者传入Comparator
compare方法
1
传入Comparator时,需要实现这个方法
compareTo方法
1
2
让java知道如何比较自定义对象
实现comparable接口时需要实现这个方法
1
int(),list(),set(),len()
1
match case
1
if isinstance(x, (int, float))
1
2
3
4
5
6
7
8
9
10
java:
整型 byte short int long
浮点 float double

''用于字符char
""用于字符串String

空值null

常量final PI;

运算符

1
2
3
4
python
/: 结果为小数
//:结果为整数
%
1
2
3
java
/ 结果为整数
%

编码

1
2
3
4
ASCII:一个字节表示一个字符
Unicode:2个字节
UTF-8:对unicode的升级,各种语言所需的字节数不一样,减少空间浪费
在计算机内存中使用unicode编码,存储和传输使用utf-8编码
1
2
3
4
5
6
7
8
9
10
python:
ord()和chr()函数分别获取字符的整数表示和字符形式

x = b'ABC' 如果要对str进行传输或者磁盘存储需要转换成以bytes为单位
'ABC'.encode('ascii')
'中文'.encode('utf-8')

反过来,如果我们从网络或磁盘上读取了字节流,那么读到的数据就是bytes。要把bytes变为str,就需要用decode()方法
b'ABC'.decode('ascii')
b'\xe4\xb8\xad\xe6\x96\x87'.decode('utf-8')
1
2
switch case