1.Math 类
Java 的 Math 包含了用于执行基本数学运算的属性和方法,如初等指数、对数、平方根和三角函数。
Math 的方法都被定义为 static 形式,通过 Math 类可以在主函数中直接调用。
1public class Test {
2 public static void main (String []args)
3 {
4 System.out.println("90 度的正弦值:" + Math.sin(Math.PI/2));
5 System.out.println("0度的余弦值:" + Math.cos(0));
6 System.out.println("60度的正切值:" + Math.tan(Math.PI/3));
7 System.out.println("1的反正切值: " + Math.atan(1));
8 System.out.println("π/2的角度值:" + Math.toDegrees(Math.PI/2));
9 System.out.println(Math.PI);
10 }
11}
以上实例编译运行结果如下:
1 90 度的正弦值:1.0
2 0度的余弦值:1.0
3 60度的正切值:1.7320508075688767
4 1的反正切值: 0.7853981633974483
5 π/2的角度值:90.0
6 3.141592653589793
除了以上方法 Math 类中还有很多其他方法
min()
返回两个参数中的最小值。
max()
返回两个参数中的最大值。
2.sort排序
导入相应的包 java.util.Arrays;才能调用该方法
直接调用Arrays类的sort方法排序之后数组里面的值就是从小到大排列的了。
经过排序之后直接返回数组的最后一个下标值就是最大值了
1 import java.util.Arrays;//导入包
2 public class Solution {
3 /**
4 *
5 * @param array: array represents an array
6 * @return : represents the maximum value of the array to be returned
7 */
8 public int getMax(int[] array) {
9 // write your code here
10 //调用数组排序封装类
11 Arrays.sort(array);
12
13 return array[array.length-1];
14 }
15}
3.最大、最小的整型
int max = Integer.MAX_VALUE;
int min = Integer.MIN_VALUE;
4.增强for循环——for each
循环,直接迭代数组的每个元素:
格式如下:
1for (元素的数据类型 变量: Collection 集合 or 数组) {
2 // 写操作代码
3}
注意:增强 for 循环必须有被遍历的目标,目标只能是 Collection 或者是数组,而且增强 for 循环只能用作遍历。
public class Main {
public static void main(String[] args) {
int[] ns = { 1, 4, 9, 16, 25 };
for (int n : ns) {
System.out.println(n);
}
}
}
注意:在for (int n : ns)
循环中,变量n
直接拿到ns
数组的元素,而不是索引。
显然for each
循环更加简洁。但是,for each
循环无法拿到数组的索引,因此,到底用哪一种for
循环,取决于我们的需要。
5.String类型
(1)Java中字符串类型首字母大写:String
(2)字符串内容匹配
public class Solution {
public String getRange(String level) {
String str = "";
if (level.equals("A")) //level.equals("A"):字符串内容匹配,
str = "90~100";
}
return str;
}
}
(3)charAt 方法
获取 String
类型中指定索引的元素,可以想到使用类方法,去 API
中找到对应的方法。
返回指定索引的 char 值:
charAt(int index):返回指定位置的 char 值,索引范围为从 0 到 length() - 1
public class Solution {
public char getIndexOne(String str) {
// 返回指定索引处的 char 值
return str.charAt(1);
}
}
(4)toCharArray 方法
可以把一个字符串变成一个数组,使用数组获取元素的方法获取值。
public class Solution {
3 public char getIndexOne(String str) {
4 char[] chars = str.toCharArray();
5
6 return chars[1];
7 }
8}
(5)字符串的创建:
1 创建字符串的简单方式:
String str = "lintcode";
2 用构造函数创建字符串:
String str = new String("lintcode");
(6)连接字符串:
String 类提供了两种连接两个字符串的方法:
concat(String str):将指定的字符串连接到该字符串的末尾
'+' 操作符:"Hello," + "lintcode" + "!"
(7)字符串大小:(数组和字符串都可以用length)
length():返回字符串的长度,空字符串的长度返回 0
示例
1public class Test {
2 public static void main(String[] args) {
3 String Str1 = new String("lintCode");
4 String Str2 = new String("");
5
6 System.out.print("字符串 Str1 长度 :");
7 System.out.println(Str1.length());
8 System.out.print("字符串 Str2 长度 :");
9 System.out.println(Str2.length());
10 }
11}
以上程序执行结果为:
1字符串 Str1 长度 :8
2字符串 Str2 长度 :0
要获取字符串的长度,数组中提供了 length
方法,可以获取数组的长度,我们可以先把字符串转换成字符数组,然后通过字符数组调用 length
方法来获取字符数组的长度,从而得出字符串的长度。
源代码
1public class Solution {
2 public int getStringLength(String str) {
3 // 将传入的字符串转换成字符数组
4 char[] array = str.toCharArray();
5 // 返回数组调用获取长度的方法,得到的是字符数组的长度
6 return array.length;
7 }
8}
(8)拆分字符串:
1split(String regex):根据匹配给定的正则表达式来拆分字符串
示例:
1class Main {
2 public static void main(String[] args) {
3 String str = new String("Welcome-to-LintCode");
4
5 System.out.println("- 分隔符返回值 :");
6
7 for (String retval : str.split("-")) {
8 System.out.println(retval);
9 }
10 }
11}
以上程序执行结果为:
- 分隔符返回值 :3
Welcome
to
LintCode
(9)截取字符串:
substring(int beginIndex):返回一个从 beginIndex 索引到末尾的字符串
substring(int beginIndex, int endIndex):返回一个从返回一个从 beginIndex 索引到 endIndex 索引(不包括)的字符串
示例:
1public class Main {
2 public static void main(String[] args) {
3 String Str = new String("This is text");
4
5 System.out.print("返回值 :");
6 System.out.println(Str.substring(4));
7
8 System.out.print("返回值 :");
9 System.out.println(Str.substring(4, 10));
10 }
11}
以上程序执行结果为:
1返回值 : is text
2返回值 : is te
(10)翻转字符串
reverse()
public class Solution {
2 /**
3 * @param str: represents the string passed in
4 * @return: represents the element whose index
5 * is the last digit
6 */
7 public char getLastIndex(String str) {
8 // write your code here
9 StringBuilder sb = new StringBuilder(str);
10 sb.reverse();
11 String s = sb.toString();
12 char ch = s.charAt(0);
13 return ch;
14 }
15}
StringBuilder对象则代表一个字符序列可变的字符串,当一个StringBuilder被创建以后,通过StringBuilder提供的append()、insert()、reverse()、setCharAt()、setLength()等方法可以改变这个字符串对象的字符序列。一旦通过StringBuilder生成了最终想要的字符串,就可以调用它的toString()方法将其转换为一个String对象。
StringBuilder是一个类,可以用来处理字符串,最简单的用法:
StringBuilder sb=new StringBuilder();
sb.Append("123");
sb.Append("456");
string str=sb.ToString();
最后得到的str字符串的值就是"123456",这种用法要比直接字符串相加效率高,比如:
string s1=“123”;
string s2=“456”;
string str=s1+s2;
得到的结果相同,但在处理大规模的字符串的时候第二种方法效率会变低。
6.创建对象,给对象属性赋值并且打印
解法一:通过对象名调用方法和属性
解题思路
本题要创建对象,给对象属性赋值并且打印。我们首先需要根据 Employee
类创建这个类的对象,然后可以使用这个对象调用 Employee
类中的属性和方法。其中有给属性赋值的方法 setXxx()
、获取属性的方法 getXxx()
。
源代码
1public class Main { 2 public static void main(String[] args) { 3 Employee employee1 = new Employee(); 4 employee1.setName("zhangsan"); 5 employee1.setAge(21); 6 employee1.setTelephone("13245667890"); 7 employee1.setOccupation("Senior Engineer"); 8 employee1.setSalary(100000); 9 employee1.printInfo(); 10 11 Employee employee2 = new Employee(); 12 employee2.setName("lisi"); 13 employee2.setAge(22); 14 employee2.setTelephone("13245667891"); 15 employee2.setOccupation("Junior Engineer"); 16 employee2.setSalary(80000); 17 employee2.printInfo(); 18 } 19}
解法二:通过对象名直接调用属性
解题思路
本题要创建对象,给对象属性赋值并且打印。在 Java 面向对象中创建的对象不仅可以使用 setXxx()
来给属性赋值,使用 getXxx()
来获取属性的值,还可以直接使用对象名来给属性赋值。
源代码
public class Main {
2 public static void main(String[] args) {
3 Employee employee1 = new Employee();
4 employee1.name = "zhangsan";
5 employee1.age = 21;
6 employee1.telephone = "13245667890";
7 employee1.occupation = "Senior Engineer";
8 employee1.salary = 100000;
9 employee1.printInfo();
10
11 Employee employee2 = new Employee();
12 employee2.name = "lisi";
13 employee2.age = 22;
14 employee2.telephone = "13245667891";
15 employee2.occupation = "Junior Engineer";
16 employee2.salary = 80000;
17 employee2.printInfo();
18 }
19}
知识要点
创建对象
对象是根据类创建的。在
Java
中,使用关键字new
来创建一个新的对象。创建对象需要以下三步:
- 声明:声明一个对象,包括对象名称和对象类型。
- 实例化:使用关键字
new
来创建一个对象。- 初始化:使用
new
创建对象时,会调用构造方法初始化对象。
Java
常用的对象创建格式为:类名 对象名 =new
类名();示例:
1public class Student { 2 String name; 3 String age; 4 5 // 无参构造方法 6 public Employee() { 7 } 8 9 // 有参构造方法 10 public Employee(String name, String occupation, String telephone, int a ge, int salary) { 11 this.name = name; 12 this.occupation = occupation; 13 this.telephone = telephone; 14 this.age = age; 15 this.salary = salary; 16 } 17 18 // setXxx 方法 19 public void setName(String name) { 20 this.name = name; 21 } 22 23 // getXxx 方法 24 public String getName() { 25 return name; 26 } 27 28 public void setAge(int age) { 29 this.age = age; 30 } 31 32 public int getAge() { 33 return age; 34 } 35 36}
public class Main { 2 public static void main(String[] args) { 3 // 创建关于 Student 类的对象,可以访问 Student 类中的属性和方法 4 Student student = new Student(); 5 // 通过 setXxx() 给属性 name 赋值 6 student.setName("zhangsan"); 7 // 通过 setXxx() 给属性 age 赋值 8 student.setAge(18); 9 // 打印通过 getXxx() 获取属性 name 的值 10 System.out.println(student.getName()); 11 // 打印通过 getXxx() 获取属性 age 的值 12 System.out.println(student.getAge()); 13 } 14}
以上实例编译运行结果如下:
1zhangsan 218
7.编写对象属性的赋值方法和打印方法
给属性赋值的方法我们可以使用 setXxx
来实现, setXxx
的结构为:
public void setXxx(属性的类型 属性名称) {
this.属性名称 = 属性名称
}
解法一:setter 方法 和 println 方法
解题思路
Employee 类对属性设置值时,使用的是 setter 方法,那么在 Employee 类中要添加对应的方法,根据样例看出来每次输出一个语句都要换行,可以使用标准输出流中的换行打印。
源代码
public class Employee {
2 String name;
3 String occupation;
4 String telephone;
5 int age;
6 int salary;
7
8 public void setName(String name) {
9 this.name = name;
10 }
11
12 public void setAge(int age) {
13 this.age = age;
14 }
15
16 public void setTelephone(String telephone) {
17 this.telephone = telephone;
18 }
19
20 public void setOccupation(String occupation) {
21 this.occupation = occupation;
22 }
23
24 public void setSalary(int salary) {
25 this.salary = salary;
26 }
27
28 public void printInfo() {
29 System.out.println("Name: " + name);
30 System.out.println("Age: " + age);
31 System.out.println("Telephone: " + telephone);
32 System.out.println("Occupation: " + occupation);
33 System.out.println("Salary: " + salary);
34 }
35}
解法二:setter 方法 、println 方法 和 \r,\n 回车换行符
解题思路
Employee 类对属性设置值时,使用的是 setter 方法,那么在 Employee 类中要添加对应的方法,根据样例看出来每次输出一个语句都要换行,可以在输出语句中加入换行符 \n。
public class Employee {
2 String name;
3 String occupation;
4 String telephone;
5 int age;
6 int salary;
7
8 public void setName(String name) {
9 this.name = name;
10 }
11
12 public void setAge(int age) {
13 this.age = age;
14 }
15
16 public void setTelephone(String telephone) {
17 this.telephone = telephone;
18 }
19
20 public void setOccupation(String occupation) {
21 this.occupation = occupation;
22 }
23
24 public void setSalary(int salary) {
25 this.salary = salary;
26 }
27
28 public void printInfo() {
29 System.out.println("Name: " + name + "\n" + "Age: " + age + "\n" +
30 "Telephone: " + telephone + "\n" + "Occupation: " + occupation +
31 "\n" + "Salary: " + salary);
32 }
33}
知识要点
基本语法: setter 方法
给成员变量赋值有两种方法,一是使用构造方法给属性进行初始化,二是使用 setter 方法。
示例:构造方法初始化变量:
public class Main {
2 public static void main(String[] args) {
3 Student student = new Student("zhangsan", 23);
4 System.out.println("name: " + student.name);
5 System.out.println("age: " + student.age);
6 }
7}
8
9
class Student {
11 public String name;
12 public int age;
13
14 public Student() {//无参数的构造函数1
15 }
16
17 public Student(String name, int age) {//当自己创建有参数的构造函数时要先写无参数的构造函数1
18 this.name = name;
19 this.age = age;
20 }
21}
以上程序的运行结果是:
1name: zhangsan
2age: 23
示例:setter 方法初始化变量:
1public class Employee {
2 String name;
3 String occupation;
4 String telephone;
5 int age;
6 int salary;
7
8 public void setName(String name) {
9 this.name = name;
10 }
11
12 public void setAge(int age) {
13 this.age = age;
14 }
15
16 public void setTelephone(String telephone) {
17 this.telephone = telephone;
18 }
19
20 public void setOccupation(String occupation) {
21 this.occupation = occupation;
22 }
23
24 public void setSalary(int salary) {
25 this.salary = salary;
26 }
27
28 public void printInfo() {
29 System.out.println("Name: " + name + "\r\n" + "Age: " + age + "\r\n" +
30 "Telephone: " + telephone + "\r\n" + "Occupation: " + occupation +
31 "\r\n" + "Salary: " + salary);
32 }
33}
以上程序的运行结果是:
1name: lisi
2age: 24
注意:
对于 private 修饰的成员变量,在本类以外的地方,只能通过 setter 和 getter 方法进行访问。
知识要点
基本语法: 回车换行符 \r \n
\n 是换行符,光标下移一格,\r 是回车符,使光标达到行首。
示例:构造方法初始化变量:
1public class Main {
2 public static void main(String[] args) {
3 String name = "张三";
4 int age = 23;
5 String gender = "男";
6 // 使光标到当前行的最左侧
7 System.out.print(name + "\r");
8 // 换行
9 System.out.print(age + "\n");
10 System.out.println(gender);
11 System.out.println("======================");
12 System.out.print(name + "\r\n");
13 // 换行
14 System.out.print(age + "\n");
15 System.out.print(gender);
16 }
17}
以上程序的运行结果是:
123
2男
3======================
4张三
523
6男
8.位运算 a左移三位 == a*2*2*2
import java.util.Scanner;//导入包
2
3public class Main {
4 public static void main(String[] args) {
5 // write your code here
6 // read data from console
7
8 // output the answer to the console according to the
9 // requirements of the question
10 Scanner input = new Scanner(System.in);//读取
11 long a=input.nextLong();//转换为long型
12 System.out.println(a<<3);
13 }
14}
输入
和输出相比,Java的输入就要复杂得多。
我们先看一个从控制台读取一个字符串和一个整数的例子:
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); // 创建Scanner对象 System.out.print("Input your name: "); // 打印提示 String name = scanner.nextLine(); // 读取一行输入并获取字符串 System.out.print("Input your age: "); // 打印提示 int age = scanner.nextInt(); // 读取一行输入并获取整数 System.out.printf("Hi, %s, you are %d\n", name, age); // 格式化输出 } }
首先,我们通过
import
语句导入java.util.Scanner
,import
是导入某个类的语句,必须放到Java源代码的开头。然后,创建
Scanner
对象并传入System.in
。System.out
代表标准输出流,而System.in
代表标准输入流。直接使用System.in
读取用户输入虽然是可以的,但需要更复杂的代码,而通过Scanner
就可以简化后续的代码。有了
Scanner
对象后,要读取用户输入的字符串,使用scanner.nextLine()
,要读取用户输入的整数,使用scanner.nextInt()
。Scanner
会自动转换数据类型,因此不必手动转换。Input your name: Bob Input your age: 12 Hi, Bob, you are 12
9.
在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。
抽象类除了不能实例化对象之外,类的其它功能依然存在,成员变量、成员方法和构造方法的访问方式和普通类一样。
由于抽象类不能实例化对象,所以抽象类必须被继承,才能被使用。也是因为这个原因,通常在设计阶段决定要不要设计抽象类。
Shape.Java
public abstract class Shape { public abstract double area(); }
Main.Java
import java.util.*; class Main { public static void main(String[] args) { Square square = new Square(Integer.parseInt(args[0])); Circle circle = new Circle(Integer.parseInt(args[0])); System.out.println(square.area()); System.out.println(String.format("%.3f", circle.area())); } }
源代码
Circle.java
1public class Circle extends Shape { 2 public int radius; 3 4 public Circle(int radius) { 5 this.radius = radius; 6 } 7 8 @Override 9 public double area() { 10 return radius * radius * Math.PI; 11 } 12}
Square.java
1public class Square extends Shape { 2 public int sideLength; 3 4 public Square(int sideLength) { 5 this.sideLength = sideLength; 6 } 7 8 @Override 9 public double area() { 10 return sideLength * sideLength; 11 } 12}
知识要点
继承
继承的概念
继承是
java
面向对象编程技术的一块基石,因为它允许创建分等级层次的类。
继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。解法一:继承、重写、
Math
类解题思路
本题要实现计算面积的方法,题目中要求实现计算正方形和圆形面积的方法,我们已知在
Shape.java
中定义好了一个计算面积的方法,所以需要在Square.java
和CieCle.java
中分别实现计算正方形面积和圆形面积的具体方法,因此需要重写计算面积的方法。源代码
Circle.java
1public class Circle extends Shape { 2 public int radius; 3 4 public Circle(int radius) { 5 this.radius = radius; 6 } 7 8 @Override 9 public double area() { 10 return radius * radius * Math.PI; 11 } 12}
Square.java
1public class Square extends Shape { 2 public int sideLength; 3 4 public Square(int sideLength) { 5 this.sideLength = sideLength; 6 } 7 8 @Override 9 public double area() { 10 return sideLength * sideLength; 11 } 12}
知识要点
继承
继承的概念
继承是
java
面向对象编程技术的一块基石,因为它允许创建分等级层次的类。
继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。类的继承格式
1class 父类 { 2} 3 4class 子类 extends 父类 { 5}
知识要点
继承
继承的概念
继承是
java
面向对象编程技术的一块基石,因为它允许创建分等级层次的类。
继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。类的继承格式
class 父类 { 2} 3 class 子类 extends 父类 { 5}
示例
Person
类1public class Person { 2 String name; 3 int age; 4 5 public Person(String name, int age) { 6 this.name = name; 7 this.age = age; 8 } 9 public void print() { 10 System.out.println("我是: " + name); 11 System.out.println("我的年龄是: " + age); 12 } 13}
Student
类1public class Student extends Person { 2 public Student(String name, int age) { 3 super(name, age); 4}
Teacher
类1public class Teacher extends Person { 2 public Teacher(String name, int age) { 3 super(name, age); 4}
Main
类1public class Main { 2 public static void main(String[] args) { 3 Student student = new Student(); 4 student.name = "student"; 5 student.age = 18; 6 student.print(); 7 8 Teacher teacher = new Teacher(); 9 teacher.name = "teacher"; 10 teacher.age = 30; 11 teacher.print(); 12 } 13}
以上实例编译运行结果如下:
1我是: student 2我的年龄是: 18; 3我是: teacher 4我的年龄是: 30
重写
定义
重写是子类对父类的允许访问的方法的实现过程进行重新编写,返回值和形参都不能改变。即外壳不变,核心重写!
示例:
1class Animal { 2 public void eat() { 3 System.out.println("动物喜欢吃东西"); 4 } 5} 6 class Dog extends Animal { 7 public void eat() { 8 System.out.println("狗喜欢吃骨头"); 9 } 10} 11public class TestDog { 12 public static void main(String args[]) { 13 // Animal 对象 14 Animal a = new Animal(); 15 // Dog 对象 16 Animal b = new Dog(); 17 18 // 执行 Animal 类的方法 19 a.eat(); 20 //执行 Dog 类的方法 21 b.eat(); 22 } 23}
以上实例编译运行结果如下:
1动物喜欢吃东西 2狗喜欢吃骨头
Math
类说明
Java
的Math
包含了用于执行基本数学运算的属性和方法,如初等指数、对数、平方根和三角函数。Math
的方法都被定义为static
形式,通过Math
类可以在主函数中直接调用。1public class Test { 2 public static void main (String []args) 3 { 4 System.out.println("90 度的正弦值:" + Math.sin(Math.PI/2)); 5 System.out.println("0 度的余弦值:" + Math.cos(0)); 6 System.out.println("60 度的正切值:" + Math.tan(Math.PI/3)); 7 System.out.println("1 的反正切值: " + Math.atan(1)); 8 System.out.println("π/2 的角度值:" + Math.toDegrees(Math.PI/2)); 9 System.out.println(Math.PI); 10 } 11}
以上实例编译运行结果如下:
190 度的正弦值:1.0 20 度的余弦值:1.0 360 度的正切值:1.7320508075688767 41 的反正切值: 0.7853981633974483 5π/2 的角度值:90.0 63.141592653589793
Math
类中的方法很多,不一一列举,有需要去Java API
文档查阅。
多态1
所谓多态,是用父类的类型去接收子类的对象
当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法。
定义
多态是同一个行为具有多个不同表现形式或形态的能力。
多态就是同一个接口,使用不同的实例而执行不同操作。多态存在的三个必要条件
- 继承
- 重写
- 父类引用指向子类对象:
Parent p = new Child();
示例:
1public class Test { 2 public static void main(String[] args) { 3 show(new Cat()); // 以 Cat 对象调用 show 方法 4 show(new Dog()); // 以 Dog 对象调用 show 方法 5 6 Animal a = new Cat(); // 向上转型 7 a.eat(); // 调用的是 Cat 的 eat 8 Cat c = (Cat)a; // 向下转型 9 c.work(); // 调用的是 Cat 的 work 10 } 11 12 public static void show(Animal a) { 13 a.eat(); 14 // 类型判断 15 if (a instanceof Cat) { // 猫做的事情 16 Cat c = (Cat)a; 17 c.work(); 18 } else if (a instanceof Dog) { // 狗做的事情 19 Dog c = (Dog)a; 20 c.work(); 21 } 22 } 23} 24abstract class Animal { 25 abstract void eat(); 26} 27class Cat extends Animal { 28 public void eat() { 29 System.out.println("吃鱼"); 30 } 31 public void work() { 32 System.out.println("抓老鼠"); 33 } 34} 35class Dog extends Animal { 36 public void eat() { 37 System.out.println("吃骨头"); 38 } 39 public void work() { 40 System.out.println("看家"); 41 } 42}
以上实例编译运行的结果是:
1吃鱼 2抓老鼠 3吃骨头 4看家 5吃鱼 6抓老鼠
多态2
解法一:对象、多态
解题思路
本题要实现多态方式调用绘制图形方法,在
Figure.java
中有个onDraw
方法,Parallelogram.java
和Triangle.java
都继承了Figure.java
并且重写了onDraw
方法。我们需要使用多态的知识去创建对象,并且使用该对象调用绘制图形的方法。源代码
Main.java
1public class Main { 2 public static void main(String[] args) { 3 Figure figure1; 4 Figure figure2; 5 Figure figure3; 6 // 创建 Figure 类的对象 7 figure1 = new Figure(); 8 figure1.onDraw(); 9 // 多态的方式创建对象 10 figure2 = new Triangle(); 11 figure2.onDraw(); 12 // 多态的方式创建对象 13 figure3 = new Parallelogram(); 14 figure3.onDraw(); 15 } 16}
解法二:对象
解题思路
本题要实现多态方式调用绘制图形方法,在
Figure.java
中有个onDraw
方法,Parallelogram.java
和Triangle.java
都继承了Figure.java
并且重写了onDraw
方法。我们需要使用对象的知识去创建对象,并且使用该对象调用绘制图形的方法。源代码
Main.java
1public class Main { 2 public static void main(String[] args) { 3 Figure figure; 4 Triangle triangle; 5 Parallelogram parallelogram; 6 // 创建 Figure 类的对象 7 figure = new Figure(); 8 figure.onDraw(); 9 // 创建 Triangle 类的对象 10 triangle = new Triangle(); 11 triangle.onDraw(); 12 // 创建 Parallelogram 类的对象 13 parallelogram = new Parallelogram(); 14 parallelogram.onDraw(); 15 } 16}
知识要点
对象
对象是根据类创建的。在
Java
中,使用关键字new
来创建一个新的对象。创建对象需要以下三步:
- 声明:声明一个对象,包括对象名称和对象类型。
- 实例化:使用关键字
new
来创建一个对象。- 初始化:使用
new
创建对象时,会调用构造方法初始化对象。示例:
1public class Student { 2 String name; 3 String age; 4 5 // 无参构造方法 6 public Employee() { 7 } 8 9 // 有参构造方法 10 public Employee(String name, String occupation, String telephone, int a ge, int salary) { 11 this.name = name; 12 this.occupation = occupation; 13 this.telephone = telephone; 14 this.age = age; 15 this.salary = salary; 16 } 17 18 // setXxx 方法 19 public void setName(String name) { 20 this.name = name; 21 } 22 23 // getXxx 方法 24 public String getName() { 25 return name; 26 } 27 28 public void setAge(int age) { 29 this.age = age; 30 } 31 32 public int getAge() { 33 return age; 34 } 35 36}
1public class Main { 2 public static void main(String[] args) { 3 // 创建关于 Student 类的对象,可以访问 Student 类中的属性和方法 4 Student student = new Student(); 5 // 通过 setXxx() 给属性 name 赋值 6 student.setName("zhangsan"); 7 // 通过 setXxx() 给属性 age 赋值 8 student.setAge(18); 9 // 打印通过 getXxx() 获取属性 name 的值 10 System.out.println(student.getName()); 11 // 打印通过 getXxx() 获取属性 age 的值 12 System.out.println(student.getAge()); 13 } 14}
以上实例编译运行结果如下:
1zhangsan 218
子类可以使用
super
函数来访问父类的构造方法。由于父类的
name
和id
属性都被private
修饰符修饰,子类是无法直接访问的,所以不能直接在子类的构造函数中使用super.属性名
的方式来获取父类的属性。由于
super();
默认存在于任何构造方法的第一行,所以在无参构造方法中可以不写super();
。如果类中声明了有参构造方法,类中默认的无参构造方法会被覆盖,如果想要使用无参构造方法来创建对象,就需要再创建一个无参构造方法。
10.对象
- static{}(即static块),会在类被加载的时候执行且仅会被执行一次,一般用来初始化静态变量和调用静态方法,静态类也这样。
- 1、用Class.forName()显示加载的时候;
- 2、实例化一个类的时候,如将main()函数的内容改为:Test t=new Test();//这种形式其实和1相比,原理是相同的,都是显示的加载这个类,读者可以验证Test t=new Test();和Test t=(Test)Class.forName().newInstance();这两条语句效果相同。
3、调用类的静态方法的时候,如将main()函数的内容改为:Test.display();
4、调用类的静态变量的时候,如将main()函数的内容改为:System.out.println(Test.X);
- 创建对象时,会调用对应类的构造方法,请注意构造方法的书写格式
- 构造方法运行前,会先运行静态代码块
子类可以使用
super
函数来访问父类的构造方法。由于父类的
name
和id
属性都被private
修饰符修饰,子类是无法直接访问的,所以不能直接在子类的构造函数中使用super.属性名
的方式来获取父类的属性。由于
super();
默认存在于任何构造方法的第一行,所以在无参构造方法中可以不写super();
。如果类中声明了有参构造方法,类中默认的无参构造方法会被覆盖,如果想要使用无参构造方法来创建对象,就需要再创建一个无参构造方法。
问题如下:
public class Father { static { System.out.println("Father's message:"); } private String name = "Liu Bei"; private int id = 1; // write your code here public void introduction() { System.out.println("name: " + name + ", id: " + id + "."); } } public class Grandson extends Son { static { System.out.println("Grandson's message:"); } // write your code here public Grandson(String name, int id){ } } public class Son extends Father { static { System.out.println("Son's message:"); } // write your code here } import java.util.*; class Main { public static void main(String[] args) { Father father = new Father(); father.introduction(); Son son = new Son("Liu Shan", 2); son.introduction(); Grandson grandson = new Grandson("Liu Chen", 3); grandson.introduction(); } }
解法:使用 super 关键字
解题思路
由题目可知,在
Main
中会调用无参构造创建father
对象,有参构造会创建son
与grandson
对象,但类Father
中缺少有参构造与无参构造,所以要在Father
中补全,且类Son
与Grandson
需要创建有参构造,只需要直接调用super(name,id);
即可,而不需要再写有参构造了。源代码
java
1public class Father { 2 static { 3 System.out.println("Father's message:"); 4 } 5 6 private String name = "Liu Bei"; 7 private int id = 1; 8 9 /** 10 * 11 * @param name: Father's name 12 * @param id: Father's id 13 */ 14 public Father(String name, int id) { 15 this.name = name; 16 this.id = id; 17 } 18 19 public Father() { 20 } 21 22 public void introduction() { 23 System.out.println("name: " + name + ", id: " + id + "."); 24 } 25} 26 27 28public class Grandson extends Son { 29 static { 30 System.out.println("Grandson's message:"); 31 } 32 33 /** 34 * 35 * @param name: Grandson's name 36 * @param id: Grandson's id 37 */ 38 public Grandson(String name, int id) { 39 super(name, id); 40 } 41} 42 43 44public class Son extends Father { 45 static { 46 System.out.println("Son's message:"); 47 } 48 49 /** 50 * 51 * @param name: Son's name 52 * @param id: Son's id 53 */ 54 public Son(String name, int id) { 55 super(name, id); 56 } 57}
知识要点
基本语法:super关键字
由于子类不能继承父类的构造方法,因此,要调用父类的构造方法,必须在子类的构造方法体的第一行使用
super()
方法。该方法会调用父类相应的构造方法来完成子类对象的初始化工作。在以下情况下需要使用
super
关键字:在类的构造方法中,通过super
语句调用该类的父类的构造方法。
在子类中访问父类中的成员。- 一. 使用 super 调用父类的构造方法
子类可以通过
super
关键字来调用一个由父类定义的构造方法,格式如下:1super(parameter-list);
其中,
parameter-list
指定了父类中构造方法所需的所有参数。super()
必须是在子类构造方法的主体第一行。
例如,在Person
类中指定了两个构造方法。示例代码如下:1public People(String name, int age, String sex, String sn) { 2 this.name = name; 3 this.age = age; 4 this.sex = sex; 5 this.sn = sn; 6} 7 8public People(String name, String sn) { 9 this.name = name; 10 this.sn = sn; 11}
那么,
Student
类继承了Person
类,就可以使用super
语句来定义Student
类的构造方法。示例代码如下:1public Student(String name, int age, String sex, String sn, String stuno, String department) { 2 // 调用父类中含有4个参数的构造方法 3 super(name, age, sex, sn); 4 this.stuNo = stuno; 5 this.department = department; 6} 7 8public Student(String name, String sn, String stuNo) {. 9 // 调用父类中含有两个参数的构造方法 10 super(name, sn); 11 this.stuNo = stuNo; 12}
从上述
Student
类构造方法代码可以看出,super
用来直接调用父类中的构造方法,使用它可以使书写代码更简洁方便。二.使用 super 访问父类成员
使用
super
访问父类中的成员与this
关键字的使用相似,只不过它引用的是子类的父类,基本形式如下:1super.member
其中,
member
是父类中的方法或属性名称。这种形式多用于子类的成员名隐藏了父类中的同名成员的情况。在
Animal
类和Cat
类中分别定义了public
类型的name
属性和private
类型的name
属性,并且Cat
类继承Animal
类。那么,我们可以在Cat
类中通过super
关键字来访问父类Animal
中的name
属性,通过this
关键字来访问本类中的name
属性,如下面的代码:1//父类Animal的定义 2public class Animal { 3 public String name; //动物名字 4} 5 6 7//子类Cat的定义 8public class Cat extends Animal { 9 private String name; //名字 10 11 public Cat(String aname, String dname) { 12 super.name = aname; //通过super关键字来访问父类中的name属性 13 this.name = dname; //通过this关键字来访问本类中的name属性 14 } 15 16 public String toString() { 17 return "我是" + super.name + ",我的名字叫" + this.name; 18 } 19 20 public static void main(String[] args) { 21 Animal cat = new Cat("动物", "喵星人"); 22 System.out.println(cat); 23 } 24}
上述代码演示了使用
super
实现子类的成员名隐藏父类中同名成员的情况。尽管Cat
类中的属性name
隐藏了Animal
类中的name
属性,但是super
允许访问父类中的name
属性。另外,super
还可以用于调用被子类隐藏的方法。运行程序,输出结果如下:
1我是动物,我的名字叫喵星人
11.枚举
Java
枚举是一个特殊的类,一般表示一组常量,一个年的 12 个月份,一个星期的 7 天,方向有东南西北等。Java
枚举类使用enum
关键字来定义,各个常量使用逗号,
来分割。
public enum Season { // write your code here SUMMER("Summmer", "the summer heat is sweetest with you"), AUTUMN("Autumn", "autumn winds and floodwaters rise"), WINTER("Winter", "the north wind is howling and the snow is drifting"); private String name; private String feature; Season(String name, String feature) { this.name = name; this.feature = feature; } public String getName() { return name; } public String getFeature() { return feature; } @Override public String toString() { return name + ": " + feature + "."; } } public class Main { public static void main(String[] args) { // write your code here } }
解法一:枚举
解题思路
本题要打印春夏秋冬的特点,我们需要根据枚举类
Seanson.java
中已经定义好的三个枚举写出第四个枚举,然后在Main
类中使用枚举类的相关知识实现对这四个枚举的打印。源代码
Season.java
1public enum Season { 2 // 定义了四个季节枚举 3 SPRING("Spring", "spring returns and everything comes back to life"), 4 SUMMER("Summer", "the summer heat is sweetest with you"), 5 AUTUMN("Autumn", "autumn winds and floodwaters rise"), 6 WINTER("Winter", "the north wind is howling and the snow is drifting"); 7 private String name; 8 private String feature; 9 // 有参构造方法 10 Season(String name, String feature) { 11 this.name = name; 12 this.feature = feature; 13 } 14 // getXxx 方法,可以获取私有变量的值 15 public String getName() { 16 return name; 17 } 18 19 public String getFeature() { 20 return feature; 21 } 22 // 重写了 toString 方法,返回 name 和 feature 的拼接 23 @Override 24 public String toString() { 25 return name + ": " + feature + "."; 26 } 27}
Main.java
1public class Main { 2 public static void main(String[] args) { 3 // 打印获取的枚举属性 4 System.out.println(Season.SPRING); 5 System.out.println(Season.SUMMER); 6 System.out.println(Season.AUTUMN); 7 System.out.println(Season.WINTER); 8 } 9}
或Main.java
1public class Main { 2 public static void main(String[] args) { 3 // 创建获取枚举的对象 4 Season s1 = Season.SPRING; 5 Season s2 = Season.SUMMER; 6 Season s3 = Season.AUTUMN; 7 Season s4 = Season.WINTER; 8 System.out.println(s1); 9 System.out.println(s2); 10 System.out.println(s3); 11 System.out.println(s4); 12 } 13}
示例:
定义来了一个动物的枚举类
1enum Animal { 2 DOG, CAT, MOUSE; 3} 4 5public class Test { 6 public static void main(String[] args) { 7 Animal an = Animal.DOG; 8 System.out.println(an); 9 } 10}
以上实例编译运行结果为
1DOG
12.去除空格
replace()
方法用于将目标字符串中的指定字符(串)替换成新的字符(串),其语法格式如下:str.replace(String oldChar, String newChar)
其中,
str
代表需要进行操作的字符串,oldChar
表示被替换的字符串;newChar
表示用于替换的字符串。replace()
方法会将字符串中所有oldChar
替换成newChar
。解法一:String 类中 replace 方法
解题思路
由题知要计算除掉空格的字符串的长度,首先想到如何删除字符串中的所有空格,思考
String
是否提供了相关方法,replace
方法可以,该方法可以替换字符串中指定内容。源代码
1public class Solution { 2 public int getLength(String str) { 3 str = str.replace(" ", ""); 4 5 int length = str.length(); 6 7 return length; 8 } 9}
解法二:String 类中 toCharArray 方法
解题思路
由题知要计算除掉空格的字符串的长度,可以将字符串变成字符数组,再对每一个字符做是否是空格的判断,统计不是空格的字符数量。
源代码
1public class Solution { 2 public int getLength(String str) { 3 char[] chars = str.toCharArray(); 4 int count = 0; 5 6 for (char c : chars) { 7 if (!(c == ' ')) { 8 count++; 9 } 10 } 11 12 return count; 13 } 14}
知识要点
基本语法:
String
字符串(String)是由数字、字母、下划线组成的一串字符。
字符串的创建:
11 创建字符串的简单方式: 2String str = "lintcode"; 32 用构造函数创建字符串: 4String str = new String("lintcode");
连接字符串:
String 类提供了两种连接两个字符串的方法:1concat(String str):将指定的字符串连接到该字符串的末尾 2'+' 操作符:"Hello," + "lintcode" + "!"
String 方法
返回指定索引的 char 值:
1charAt(int index):返回指定位置的 char 值,索引范围为从 0 到 length() - 1
示例:
1public class Test { 2 public static void main(String[] args) { 3 String s = "lintCode"; 4 char result = s.charAt(6); 5 System.out.println(result); 6 } 7}
以上程序执行结果为:
1d
字符串大小:
1length():返回字符串的长度,空字符串的长度返回 0
示例:
1public class Test { 2 public static void main(String[] args) { 3 String Str1 = new String("lintCode"); 4 String Str2 = new String(""); 5 6 System.out.print("字符串 Str1 长度 :"); 7 System.out.println(Str1.length()); 8 System.out.print("字符串 Str2 长度 :"); 9 System.out.println(Str2.length()); 10 } 11}
以上程序执行结果为:
1字符串 Str1 长度 :8 2字符串 Str2 长度 :0
拆分字符串:
1split(String regex):根据匹配给定的正则表达式来拆分字符串
示例:
1class Main { 2 public static void main(String[] args) { 3 String str = new String("Welcome-to-LintCode"); 4 5 System.out.println("- 分隔符返回值 :"); 6 7 for (String retval : str.split("-")) { 8 System.out.println(retval); 9 } 10 } 11}
以上程序执行结果为:
1- 分隔符返回值 :3 2Welcome 3to 4LintCode
截取字符串:
1substring(int beginIndex):返回一个从 beginIndex 索引到末尾的字符串 2substring(int beginIndex, int endIndex):返回一个从返回一个从 beginIndex 索引到 endIndex 索引(不包括)的字符串
示例:
1public class Main { 2 public static void main(String[] args) { 3 String Str = new String("This is text"); 4 5 System.out.print("返回值 :"); 6 System.out.println(Str.substring(4)); 7 8 System.out.print("返回值 :"); 9 System.out.println(Str.substring(4, 10)); 10 } 11}
以上程序执行结果为:
1返回值 : is text 2返回值 : is te
替换字符串中的内容:
1replace(char oldChar, char newChar):返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。 2String replaceAll(String regex, String replacement):使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串。
示例:
1public class Main { 2 public static void main(String[] args) { 3 String Str = new String("LintTCode"); 4 5 System.out.print("返回值 :"); 6 System.out.println(Str.replace('T', ' ')); 7 8 String Str2 = new String("www.google.com"); 9 10 System.out.print("匹配成功返回值 :"); 11 System.out.println(Str2.replaceAll("(.*)google(.*)", "baidu")); 12 System.out.print("匹配失败返回值 :"); 13 System.out.println(Str2.replaceAll("(.*)taobao(.*)", "baidu")); 14 } 15}
以上程序执行结果为:
1返回值 :Lint Code 2匹配成功返回值 :baidu 3匹配失败返回值 :www.google.com
13.输入
我们先看一个从控制台读取一个字符串和一个整数的例子:
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); // 创建Scanner对象 System.out.print("Input your name: "); // 打印提示 String name = scanner.nextLine(); // 读取一行输入并获取字符串 System.out.print("Input your age: "); // 打印提示 int age = scanner.nextInt(); // 读取一行输入并获取整数 System.out.printf("Hi, %s, you are %d\n", name, age); // 格式化输出 } }
首先,我们通过
import
语句导入java.util.Scanner
,import
是导入某个类的语句,必须放到Java源代码的开头。然后,创建
Scanner
对象并传入System.in
。System.out
代表标准输出流,而System.in
代表标准输入流。直接使用System.in
读取用户输入虽然是可以的,但需要更复杂的代码,而通过Scanner
就可以简化后续的代码。有了
Scanner
对象后,要读取用户输入的字符串,使用scanner.nextLine()
,要读取用户输入的整数,使用scanner.nextInt()
。Scanner
会自动转换数据类型,因此不必手动转换。
14. 运算符优先级
交换两个整数
// 先进行运算,再进行赋值 9 b = (a + b) - (a = b);
如果表达式中包含多个小括号,执行顺序是从左到右。
当多个运算符出现在一个表达式中,谁先谁后呢?这就涉及到运算符的优先级别的问题。在一个多运算符的表达式中,运算符优先级不同会导致最后得出的结果差别甚大。
类别 操作符 关联性 后缀 () [] . (点操作符) 左到右 一元 expr++ expr-- 从左到右 一元 ++expr --expr + - ~ ! 从右到左 乘性 * /% 左到右 加性 + - 左到右 移位 >> >>> << 左到右 关系 > >= < <= 左到右 相等 == != 左到右 按位与 & 左到右 按位异或 ^ 左到右 按位或 逻辑与 && 左到右 逻辑或 条件 ?: 从右到左 赋值 = + = - = * = / =%= >> = << =&= ^ = = 逗号 , 左到右
15.创建内部类,非静态内部类对外部成员的直接访问
要求:在外部类 Cow
中创建一个内部类 CowLeg
,并在该类中定义实例变量 float height
和 String color
,创建一个实例方法 info
,在该方法中使用 System.out.println()
对动物牛属性进行打印。
- 在内部类中的构造方法是有传参数的
- 在内部类中可以直接访问外部
private
成员非静态内部类成员可以访问外部类的
private
成员,反过来是不成立的。非静态内部类成员只在非静态内部范围可知,如果外部类需要访问非静态内部类成员,则必须创建非静态内部类对象来调用访问其实例成员。解法:创建内部类
解题思路
由题目可知,我们最终要输出三条语句,包含的牛的颜色,高度,重量,其中
weight
可以直接获取,但其他属性需要我们自定义,所以我们还需要新建一个CowLeg
的内部类,定义属性height
,color
,还需要注意,在printInfo
方法中会通过创建内部类对象而调用info
方法,所以需要新增一个有参构造函数,传入height
,color
,还需要定义一个info
方法,使其输出对应的语句,需要注意,在冒号后面需要新增一个空格。public class Cow { 3 private float weight; 4 5 public Cow(float weight) { 6 this.weight = weight; 7 } 8 9 public void printInfo(float height, String color) { 10 CowLeg c1 = new CowLeg(height, color); 11 c1.info(); 12 } 13 14 // Non-static internal classes 15 private class CowLeg { 16 // 创建对象的属性 17 private float height; 18 private String color; 19 // 创建有参构造函数 20 public CowLeg(float height, String color) { 21 this.height = height; 22 this.color = color; 23 } 24 25 public String getColor() { 26 return color; 27 } 28 29 public void setColor(String color) { 30 this.color = color; 31 } 32 33 public float getHeight() { 34 return height; 35 } 36 37 public void setHeight(float height) { 38 this.height = height; 39 } 40 // 依次是输出对应的语句 41 public void info() { 42 System.out.println("The color of the cow is: " + color); 43 System.out.println("The height of the cow is: " + height); 44 System.out.println("The weight of the cow is: " + weight); 45 } 46 } 47}
知识要点
基本语法:成员内部类
成员内部类是最普通的内部类,它的定义为位于另一个类的内部,形如下面的形式:1public class Circle { 2 double radius = 0; 3 4 public Circle(double radius) { 5 this.radius = radius; 6 } 7 // 内部类 8 class Draw { 9 public void drawSahpe() { 10 System.out.println("drawshape"); 11 } 12 } 13}
这样看起来,类
Draw
像是类Circle
的一个成员,Circle
称为外部类。成员内部类可以无条件访问外部类的所有成员属性和成员方法(包括private
成员和静态成员)。1class Circle { 2 private double radius = 0; 3 public static int count =1; 4 public Circle(double radius) { 5 this.radius = radius; 6 } 7 //内部类 8 class Draw { 9 public void drawSahpe() { 10 //外部类的private成员 11 System.out.println(radius); 12 //外部类的静态成员 13 System.out.println(count); 14 } 15 } 16}
不过要注意的是,当成员内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象,即默认情况下访问的是成员内部类的成员。如果要访问外部类的同名成员,需要以下面的形式进行访问:
1外部类.this.成员变量 2外部类.this.成员方法
虽然成员内部类可以无条件地访问外部类的成员,而外部类想访问成员内部类的成员却不是这么随心所欲了。在外部类中如果要访问成员内部类的成员,必须先创建一个成员内部类的对象,再通过指向这个对象的引用来访问:public class Test { 2 public static void main(String[] args) { 3 //第一种方式: 4 Outter outter = new Outter(); 5 Outter.Inner inner = outter.new Inner(); //必须通过Outter对象来创建 6 7 //第二种方式: 8 Outter.Inner inner1 = outter.getInnerInstance(); 9 } 10} 11 12 13class Outter { 14 private Inner inner = null; 15 16 public Outter() { 17 } 18 19 public Inner getInnerInstance() { 20 if (inner == null) { 21 inner = new Inner(); 22 } 23 24 return inner; 25 } 26 27 class Inner { 28 public Inner() { 29 } 30 } 31}
内部类可以拥有
private
访问权限、protected
访问权限、public
访问权限及包访问权限。比如上面的例子,如果成员内部类Inner
用private
修饰,则只能在外部类的内部访问,如果用public
修饰,则任何地方都能访问;如果用protected
修饰,则只能在同一个包下或者继承外部类的情况下访问;如果是默认访问权限,则只能在同一个包下访问。这一点和外部类有一点不一样,外部类只能被public
和包访问两种权限修饰。我个人是这么理解的,由于成员内部类看起来像是外部类的一个成员,所以可以像类的成员一样拥有多种权限修饰。
16.求三个数的最大值
解法一:max()方法
解题思路
使用 max()方法先求得前两个数中的最大值,再用 max()方法让前两个数中的最大值与第三个数作为参数求最大值
源代码
java
1import java.util.Scanner; 2 3public class Main { 4 public static void main(String[] args) { 5 Scanner sc = new Scanner(System.in); 6 int a = sc.nextInt(); 7 int b = sc.nextInt(); 8 int c = sc.nextInt(); 9 // 使用 max()方法先求得前两个数中的最大值,再用 max()方法让前两个数中的最大值与第三个数作为参数求最大值 10 System.out.println(Math.max(Math.max(a, b), c)); 11 } 12}
解法二:if 语句、赋值
解题思路
首先假设第一个数为最大值,将第一个数赋值给最大值变量,接下来用赋值之后的最大值变量与第二个数进行比较,若第二个数大于当前最大值变量,则将第二个数的值赋值给当前最大值变量,第三个数与第二个数的操作相同,最后输出最大值变量即可
源代码
1import java.util.Scanner; 2 3public class Main { 4 public static void main(String[] args) { 5 Scanner sc = new Scanner(System.in); 6 int a = sc.nextInt(); 7 int b = sc.nextInt(); 8 int c = sc.nextInt(); 9 int max_num = a; 10 // 若第二个数大于当前最大值变量,则将第二个数的值赋值给当前最大值变量 11 if (b > max_num) 12 { 13 max_num = b; 14 } 15 if (c > max_num) 16 { 17 max_num = c; 18 } 19 20 System.out.println(max_num); 21 } 22}
17.获取学生的信息
在一个
class
中定义的字段,我们称之为实例字段。实例字段的特点是,每个实例都有独立的字段,各个实例的同名字段互不影响。还有一种字段,是用
static
修饰的字段,称为静态字段:static field
。实例字段在每个实例中都有自己的一个独立“空间”,但是静态字段只有一个共享“空间”,所有实例都会共享该字段。举个例子:
class Person { public String name; public int age; // 定义静态字段number: public static int number; }
虽然实例可以访问静态字段,但是它们指向的其实都是
Person class
的静态字段。所以,所有实例共享一个静态字段。静态方法
有静态字段,就有静态方法。用
static
修饰的方法称为静态方法。调用实例方法必须通过一个实例变量,而调用静态方法则不需要实例变量,通过类名就可以调用。静态方法类似其它编程语言的函数。
public class Main { public static void main(String[] args) { Person.setNumber(99); System.out.println(Person.number); } } class Person { public static int number; public static void setNumber(int value) { number = value; } }
因为静态方法属于
class
而不属于实例,因此,静态方法内部,无法访问this
变量,也无法访问实例字段,它只能访问静态字段。
java允许在一个类里面定义静态类。如内部类(nested class)。
在java中,不能用static修饰顶级类(top level class)。只有内部类可以为static。
静态内部类和非静态内部类之间区别: 1. 内部静态类不需要有指向外部类的引用。但非静态内部类需要。 2. 静态类只能访问外部类的静态成员,非静态内部类能够访问外部类的静态和非静态成员。 3. 非静态内部类不能脱离外部类实体被创建,非静态内部类可以访问外部类的数据和方法,因为他就在外部类里面。
解法: 使用静态内部类属性
解题思路
由题目可知,我们最终要输出三条语句,包含学生姓名,学生编号,课程信息,而静态内部类已经给我们写好了,属性也都一一赋值了,但是只有
studentName
是static
修饰的,也就是说,当在外部类的方法中使用内部类的属性时,对于静态变量,我们可以直接通过类名去调用,但是对于非静态变量,只能通过内部类对象去调用,这点需要注意,之后在accessInnerProp
方法中输出对应的语句即可。public class Solution { 3 private static String prop1; 4 private static String prop2; 5 private static String prop3; 6 7 public Solution() { 8 } 9 10 public Solution(String prop1, String prop2, String prop3) { 11 this.prop1 = prop1; 12 this.prop2 = prop2; 13 this.prop3 = prop3; 14 } 15 16 public void accessInnerProp() { 17 // 借助类名输出 studentName 18 System.out.println("studentName:" + staticInnerClass.studentName); 19 // 借助对象名输出 studentId 20 System.out.println("studentId:" + new staticInnerClass().studentId); 21 System.out.println("studentCourse:" + 22 new staticInnerClass().studentCourse); 23 } 24 25 static class staticInnerClass { 26 // 给变量赋值 27 private static String studentName = prop1; 28 private String studentId = prop2; 29 private String studentCourse = prop3; 30 } 31}
知识要点
基本语法:静态内部类
静态内部类也是定义在另一个类里面的类,只不过在类的前面多了一个关键字static
。
静态内部类是不需要依赖于外部类的,这点和类的静态成员属性有点类似,并且它不能使用外部类的非static
成员变量或者方法,这点很好理解,因为在没有外部类的对象的情况下,可以创建静态内部类的对象,如果允许访问外部类的非static成员就会产生矛盾,因为外部类的非static
成员必须依附于具体的对象。静态内部类使用示例
1public class StaticInnerTest { 2 private static int y = 2; 3 private int x = 1; 4 5 public void test() { 6 // 借助对象输出静态内部类的属性信息 7 System.out.println(new InnerClass().a); 8 // 借助类名输出静态内部类的属性信息 9 System.out.println(InnerClass.b); 10 } 11 12 public static void main(String[] args) { 13 StaticInnerTest staticInnerTest = new StaticInnerTest(); 14 // 输出静态内部类属性 15 staticInnerTest.test(); 16 17 InnerClass innerClass = new InnerClass(); 18 // 静态内部类调用外部属性 19 innerClass.test(); 20 } 21 22 static class InnerClass { 23 private static int b = 4; 24 private int a = 3; 25 26 public void test() { 27 //无法访问 因为 x 不是静态变量 28 //System.out.println(x); 29 System.out.println(y); 30 } 31 } 32}
输出结果:
13 24 32
由结果可知,当外部类访问静态内部类成员时,如果是静态成员,需要借助类名去访问,如果是非静态成员,那么只能借助内部类对象去访问。而如果静态内部类要访问外部类的成员,只能访问static修饰的,非static修饰的变量是无法访问的。
18.
π:
double l = 2 * Math.acos(-1) * r;
Math.PI
Java Math acos()方法返回指定值的反余弦值。
反余弦是余弦函数的反函数。
acos()方法的语法为:
Math.acos(double num)
acos()参数num - 要返回其反余弦的数字,它应始终小于1。
acos()返回值返回指定数字的反余弦值
如果指定数是NaN或大于1,返回NaN
注意:返回值是介于0.0 到 pi之间的角度。
int n=Integer.parseInt(args[0]);
Integer.parseInt(args[0])中,Integer是java中的一个内置类,parseInt()是这个类的一个静态方法,这个方法的作用是把括号里面的参数(args[0])转为int型的值,比如定义一个String a="123",这时"a"是一个字符串,不能进行数值计算,如果你要让"a"能进行数值计算,你就可以用Integer.parseInt(a)这个函数把"a"转为int型再来进行数值计算。
args[0]是java中启动参数的第一个值,在命令行通过键盘可以输入,Integer.parseInt是Integer整数类的一个方法,作用是将参数解析为一个整数,如java test 100,其中100就是args[0],而运行结果是n=100
19. 获取输入的字符
获取控制台输入可通过使用
Scanner
类进行操作
- 例:
// 通过 `Scanner` 类获取控制台输入流 Scanner scanner = new Scanner(System.in); // 获取控制台输入的一个字符串 String s = scanner .next();
请注意
character
是一个字母或数字。代码:
import java.util.Scanner; 2public class Main { 3 public static void main(String[] args) { 4 // write your code here 5 Scanner myscanner = new Scanner(System.in);// 通过 `Scanner` 类获取控制台输入流 6 Character character = myscanner.next().charAt(0);//得到输入字符串的第一个字符 7 int ascii = character;//得到字符的ASCII码 8 System.out.println(ascii);//输出ASCII码 9 10 } 11}
20.最大公约数
21.给一个字符串数字取整
描述
在本题有一个
HandleAble
接口,里面包含了一个handle
的抽象方法,需要对传入的num
字符串进行一定的处理逻辑。
在Solution
类中包含一个get
方法,你需要借助匿名内部类的方式,实现HandleAble
接口的handle
方法,使其传入任意字符串类型的数字,都能返回一个去除小数点后面位数的整型。请在类名为
Solution
中的get
方法中的// write your code here
下面编写你的代码。
- 请考虑到没有小数点的情况的判断
- 当您使用字符串的拆分方法,注意匹配正则
public class Solution { /** * @param str : String type numbers * @return A rounded number */ public int get(String str) { // write your code here } }
interface HandleAble { /** * @param num : String type numbers * @return return means that the number to be returned is an int type */ int handle(String num); }
解法一: 使用字符串分割
解题思路
由题目可知,在
HandleAble
接口中含有抽象方法handle
,我们需要实现该接口,并重写里面的方法,由于只是让我们在方法中实现相应的逻辑,且题目说明了使用匿名内部类的形式,那么就好办了,在get
方法中创建对应的匿名内部类,实现handle
方法,形参为String
类型,所以可以直接去除掉小数点后面的字段,这里有两点是需要注意的:1.传入的可能是整数字符串,所以要判断字符串中是否包含小数点。
2.使用字符串的分割方法
split
,如果传入小数点,则会按正则匹配,而小数点是匹配全部,所以要进行转义在可以,形式如下1 String[] split = num.split("\\.");
最终我们将得到的数组的部分转化成整型即可,后借助内部类对象调用
handle
方法完成解答。public class Solution { 2 3 public int get(String str) { 4 HandleAble handleAble = new HandleAble() { 5 @Override 6 public int handle(String num) { 7 // 判断字符串中是否包含小数点 8 if (num.contains(".")) { 9 // 若包含 则要进行拆分 10 String[] split = num.split("\\."); 11 return Integer.parseInt(split[0]); 12 } else { 13 // 否则直接转化成整型返回即可 14 return Integer.parseInt(num); 15 } 16 } 17 }; 18 return handleAble.handle(str); 19 } 20}
解法二: 使用 Double 强转
解题思路
还是实现匿名内部类,但是里面的方法可以改变一下,因为传入的字符串都是数字类型,所以可以用
double
类型去接收,再强转为整型即可。public class Solution { public int get(String str) { HandleAble handleAble = new HandleAble() { @Override public int handle(String num) { return (int) (Double.parseDouble(num)); } };//定义 return handleAble.handle(str);//调用 } }
知识要点
基本语法:匿名内部类
匿名内部类应该是平时我们编写代码时用得最多的,在编写事件监听的代码时使用匿名内部类不但方便,而且使代码更加容易维护。下面这段代码是一段Android
事件监听代码:scan_bt.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub } }); history_bt.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub } });
这段代码为两个按钮设置监听器,这里面就使用了匿名内部类。这段代码中的:
1new OnClickListener() { 2 @Override 3 public void onClick(View v) { 4 // TODO Auto-generated method stub 5 6 } 7}
就是匿名内部类的使用。代码中需要给按钮设置监听器对象,使用匿名内部类能够在实现父类或者接口中的方法情况下同时产生一个相应的对象,但是前提是这个父类或者接口必须先存在才能这样使用。当然像下面这种写法也是可以的,跟上面使用匿名内部类达到效果相同。
class Listener1 implements View.OnClickListener { 2 @Override 3 public void onClick(View v) { 4 // TODO Auto-generated method stub 5 6 } 7} 8 9class Listener2 implements View.OnClickListener { 10 @Override 11 public void onClick(View v) { 12 // TODO Auto-generated method stub 13 14 } 15}
这种写法虽然能达到一样的效果,但是既冗长又难以维护,所以一般使用匿名内部类的方法来编写事件监听代码。同样的,匿名内部类也是不能有访问修饰符和
static
修饰符的。
匿名内部类是唯一一种没有构造器的类。正因为其没有构造器,所以匿名内部类的使用范围非常有限,大部分匿名内部类用于接口回调。匿名内部类在编译的时候由系统自动起名为Outter$1.class
。一般来说,匿名内部类用于继承其他类或是实现接口,并不需要增加额外的方法,只是对继承方法的实现或是重写。java split()的用法:1、如果用“.”作为分隔的话,必须的写法是“String.split("\\.")”;2、如果用“|”作为分隔的话,必须的写法是“String.split("\\|")”。
22.打印梅兰竹菊代表的品性
public class Solution { /** * @methods judge: Enumerate and print out the enumeration values * in the judge method */ public void printCharacter(PropertyEnum s) { switch (s) { case PlumBlossoms: System.out.println( "PlumBlossoms: A noble man who explores the waves and the snow"); break; case Orchid: System.out.println( "Orchid: A sage of the world, the fragrance of the deep valley"); break; case Bamboo: System.out.println("Bamboo: A gentleman of modesty and elegance"); break; case Chrysanthemum: System.out.println("Chrysanthemum: A hermit of the world"); break; } } public void textCharacter() { // write your code here } } public enum PropertyEnum { PlumBlossoms, Orchid, Bamboo, Chrysanthemum; } public class Main { public static void main(String[] args) { Solution solution = new Solution(); solution.textCharacter(); } }
解法一:枚举
解题思路
本题要打印梅兰竹菊的品性,在枚举类
PropertyEnum
中已经定义好了梅兰竹菊四个枚举,Solution.java
中有个printCharacter
方法,方法中传递了一个枚举类型的参数。我们可以根据printCharacter
方法中的条件语句在textCharacter
方法中实现对枚举值的访问。访问的枚举值作为printCharacter
方法的参数。可以通过
EnumClass.variable
传参形式来访问枚举实例。public class Solution { 2 public void printCharacter(PropertyEnum s) { 3 // switch...case 语句,实现对存春夏秋冬的判断,打印品性 4 switch (s) { 5 case PlumBlossoms: 6 System.out.println( 7 "PlumBlossoms: A noble man who explores the waves and the snow"); 8 break; 9 10 case Orchid: 11 System.out.println( 12 "Orchid: A sage of the world, the fragrance of the deep valley"); 13 break; 14 15 case Bamboo: 16 System.out.println("Bamboo: A gentleman of modesty and elegance"); 17 break; 18 19 case Chrysanthemum: 20 System.out.println("Chrysanthemum: A hermit of the world"); 21 break; 22 } 23 } 24 // textCharacter 方法,实现对枚举值的获取,将获取的枚举值传入 printCharacter 方法 25 public void textCharacter() { 26 printCharacter(PropertyEnum.PlumBlossoms); 27 printCharacter(PropertyEnum.Orchid); 28 printCharacter(PropertyEnum.Bamboo); 29 printCharacter(PropertyEnum.Chrysanthemum); 30 } 31}
解法二:枚举
解题思路
同解法一
源代码
public class Solution { 2 public void printCharacter(PropertyEnum s) { 3 // switch...case 语句,实现对存春夏秋冬的判断,打印品性 4 switch (s) { 5 case PlumBlossoms: 6 System.out.println( 7 "PlumBlossoms: A noble man who explores the waves and the snow"); 8 break; 9 10 case Orchid: 11 System.out.println( 12 "Orchid: A sage of the world, the fragrance of the deep valley"); 13 break; 14 15 case Bamboo: 16 System.out.println("Bamboo: A gentleman of modesty and elegance"); 17 break; 18 19 case Chrysanthemum: 20 System.out.println("Chrysanthemum: A hermit of the world"); 21 break; 22 } 23 } 24 // textCharacter 方法,实现对枚举值的获取,将获取的枚举值传入 printCharacter 方法 25 public void textCharacter() { 26 new Solution().printCharacter(PropertyEnum.PlumBlossoms); 27 new Solution().printCharacter(PropertyEnum.Orchid); 28 new Solution().printCharacter(PropertyEnum.Bamboo); 29 new Solution().printCharacter(PropertyEnum.Chrysanthemum); 30 } 31}
知识要点
枚举
Java
枚举是一个特殊的类,一般表示一组常量,比如一年的 4 个季节,一个年的 12 个月份,一个星期的 7 天,方向有东南西北等。Java
枚举类使用enum
关键字来定义,各个常量使用逗号 ',' 来分割。示例:
定义来了一个动物的枚举类
1enum Animal { 2 DOG, CAT, MOUSE; 3} 4 5public class Test { 6 public static void main(String[] args) { 7 Animal an = Animal.DOG; 8 System.out.println(an); 9 } 10}
以上实例编译运行结果为
1DOG
23.使用匿名内部类
- 创建匿名内部类必须实现其内部的抽象方法
- 创建匿名内部类不要省略末尾的分号
在匿名内部类中,可以直接访问外部类的属性,包括私有的。
public class Solution { private String name; public Solution(String name) { this.name = name; } public Animal get(){ } } public interface Animal { /** * @param food : Any animal needs food */ void eat(String food); } public class Main { public static void main(String[] args) { Solution solution = new Solution(args[0]); Animal animal = solution.get(); animal.eat(args[1]); } }
解法:匿名内部类
解题思路
通过类的构造方法创建
Animal
对象,并重写接口中的抽象方法。public class Solution { 3 private String name; 4 5 public Solution(String name) { 6 this.name = name; 7 } 8 9 public Animal get() { 10 // 创建匿名内部类对象 11 return new Animal() { 12 // 重写接口方法 13 @Override 14 public void eat(String food) { 15 System.out.println(name + " eat " + food); 16 } 17 }; 18 } 19}
知识要点
基本语法:匿名内部类
匿名内部类
匿名内部类就是没有名字的内部类。正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写;但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口。
abstract class Person { 2 public abstract void eat(); 3} 4 5 6class Child extends Person { 7 public void eat() { 8 System.out.println("eat something"); 9 } 10} 11 12 13public class Demo { 14 public static void main(String[] args) { 15 Person p = new Child(); 16 p.eat(); 17 } 18}
以上实例编译运行结果如下:
1eat something
可以看到,我们用 Child继承了 Person类,然后实现了 Child的一个实例,将其向上转型为Person类的引用。但是,如果此处的 Child类只使用一次,那么将其编写为独立的一个类岂不是很麻烦?这个时候就引入了匿名内部类。
示例:匿名内部类的基本实现:
1abstract class Person { 2 public abstract void eat(); 3} 4 5 6public class Demo { 7 public static void main(String[] args) { 8 Person p = new Person() { 9 public void eat() { 10 System.out.println("eat something"); 11 } 12 }; 13 14 p.eat(); 15 } 16}
以上实例编译运行结果如下:
1eat something
可以看到,我们直接将抽象类
Person
中的方法在大括号中实现了,这样便可以省略一个类的书写。并且,匿名内部类还能用于接口上。示例:在接口上使用匿名内部类:
1interface Person { 2 public void eat(); 3} 4 5 6public class Demo { 7 public static void main(String[] args) { 8 Person p = new Person() { 9 public void eat() { 10 System.out.println("eat something"); 11 } 12 }; 13 14 p.eat(); 15 } 16}
以上实例编译运行结果如下:
1eat something
由上面的例子可以看出,只要一个类是抽象的或是一个接口,那么其子类中的方法都可以使用匿名内部类来实现。
24.Math
算术计算方式:
1Math.sqrt() : 计算平方根 2Math.cbrt() : 计算立方根 3Math.pow(a, b) : 计算a的b次方 4Math.max( , ) : 计算最大值 5Math.min( , ) : 计算最小值 6Math.abs() : 取绝对值
实例:
1System.out.println(Math.sqrt(16)); // 4.0 2System.out.println(Math.cbrt(8)); // 2.0 3System.out.println(Math.pow(3, 2)); // 9.0 4System.out.println(Math.max(2.3, 4.5));// 4.5 5System.out.println(Math.min(2.3, 4.5));// 2.3 6 7/** 8 * abs求绝对值 9 */ 10System.out.println(Math.abs(-10.4)); // 10.4 11System.out.println(Math.abs(10.1)); // 10.1
进位:
1Math.ceil(): 天花板的意思,就是逢余进一 2Math.floor() : 地板的意思,就是逢余舍一 3Math.rint(): 四舍五入,返回double值。注意.5的时候会取偶数 4Math.round(): 四舍五入,float时返回int值,double时返回long值
实例:
1/** 2* ceil天花板的意思,就是逢余进一 3 */ 4System.out.println(Math.ceil(-10.1)); // -10.0 5System.out.println(Math.ceil(10.7)); // 11.0 6System.out.println(Math.ceil(-0.7)); // -0.0 7System.out.println(Math.ceil(0.0)); // 0.0 8System.out.println(Math.ceil(-0.0)); // -0.0 9System.out.println(Math.ceil(-1.7)); // -1.0 10 11System.out.println("-------------------"); 12 13/** 14 * floor地板的意思,就是逢余舍一 15 */ 16System.out.println(Math.floor(-10.1)); // -11.0 17System.out.println(Math.floor(10.7)); // 10.0 18System.out.println(Math.floor(-0.7)); // -1.0 19System.out.println(Math.floor(0.0)); // 0.0 20System.out.println(Math.floor(-0.0)); // -0.0 21 22System.out.println("-------------------"); 23 24/** 25 * rint 四舍五入,返回double值 注意.5的时候会取偶数 异常的尴尬=。= 26 */ 27System.out.println(Math.rint(10.1)); // 10.0 28System.out.println(Math.rint(10.7)); // 11.0 29System.out.println(Math.rint(11.5)); // 12.0 30System.out.println(Math.rint(10.5)); // 10.0 31System.out.println(Math.rint(10.51)); // 11.0 32System.out.println(Math.rint(-10.5)); // -10.0 33System.out.println(Math.rint(-11.5)); // -12.0 34System.out.println(Math.rint(-10.51)); // -11.0 35System.out.println(Math.rint(-10.6)); // -11.0 36System.out.println(Math.rint(-10.2)); // -10.0 37 38System.out.println("-------------------"); 39/** 40 * round 四舍五入,float时返回int值,double时返回long值 41 */ 42System.out.println(Math.round(10)); // 10 43System.out.println(Math.round(10.1)); // 10 44System.out.println(Math.round(10.7)); // 11 45System.out.println(Math.round(10.5)); // 11 46System.out.println(Math.round(10.51)); // 11 47System.out.println(Math.round(-10.5)); // -10 48System.out.println(Math.round(-10.51)); // -11 49System.out.println(Math.round(-10.6)); // -11 50System.out.println(Math.round(-10.2)); // -10
特殊点注意:
1int a = 1300, b = 1000; 2System.out.println(Math.ceil(a / b)); // 1 表达式A(错误使用) 3System.out.println(Math.ceil(a / (float)b)); // 2 表达式B(正确使用)
25.字符串逆序输出
解法一:字符串
解题思路
使用 java.lang.String.charAt() 方法返回指定索引处的char值。索引范围是从0到length() - 1。对于数组索引,序列的第一个char值是在索引为0,索引1,依此类推。在这道题中,我们需要逆序输出。
import java.util.*; 3 4public class Main { 5 public static void main(String[] args) { 6 Scanner sc = new Scanner(System.in); 7 String str = sc.next(); 8 List<String> list=new ArrayList(); 9 for(char c:str.toCharArray()){ 10 list.add(c+""); 11 } 12 Collections.reverse(list); 13 for(String s:list){ 14 System.out.print(s); 15 } 16 17 } 18}
解法二:for循环
解题思路
for循环从后往前遍历。在这道题中,我们需要逆序输出。
源代码
1 2import java.util.Scanner; 3 4public class Main { 5 public static void main(String[] args) { 6 Scanner sc = new Scanner(System.in); 7 String a = sc.next(); 8 for(int i = a.length() - 1; i >= 0; i--){ 9 System.out.print(a.charAt(i)); 10 } 11 } 12}
解法三
import java.util.Scanner; 2 3public class Main { 4 public static void main(String[] args) { 5 // write your code here 6 // read data from console 7 Scanner s = new Scanner(System.in); 8 String a = s.nextLine(); 9 StringBuffer b = new StringBuffer(a); 10 // output the answer to the console according to the 11 // requirements of the question 12 System.out.println(b.reverse()); 13 14 } 15}
知识要点
基本语法:字符串
Java 提供了 String 类来创建和操作字符串。
1、创建字符串
1public class Main { 2 public static void main(String[] args){ 3 String s1 = "jiuzhang_1"; // String 直接创建 4 String s2 = s1; // 相同引用 5 String s3 = new String("jiuzhang_2"); // String 对象创建 6 7 System.out.println(s1); 8 System.out.println(s2); 9 System.out.println(s3); 10 } 11} 12 13// output : 14// jiuzhang_1 15// jiuzhang_1 16// jiuzhang_2
2、合并两个字符串
1public class Main { 2 public static void main(String[] args){ 3 String str1="jiu zhang "; //创建字符串1 4 String str2="da fa hao"; //创建字符串2 5 String str=str1+str2; //字符串相加 6 7 System.out.println(str); //输出字符串 8 } 9} 10 11// output : 12// jiu zhang da fa hao
4、equals() 判断两个字符串是否相同
1public class Main { 2 public static void main(String[] args){ 3 String str1="jiu zhang "; 4 String str2="jiu zhang "; 5 String str3="da fa hao"; 6 boolean a=str1.equals(str2); 7 boolean b=str1.equals(str3); //判断两个字符串是否相同,相同输出true,否则输出false 8 9 System.out.println(a); 10 System.out.println(b); 11 } 12} 13 14// output : 15// true 16// false
5、contains() 判断某个字符串是否另一个字符串中出现过
1public class Main { 2 public static void main(String[] args) 3 { 4 String str1="jiu zhang"; 5 String str2="jiu"; 6 String str3="zhuang"; 7 boolean a=str1.contains(str2); 8 //子字符串是否被包含在此字符串之中,包含输出true,否则输出false 9 boolean b=str1.contains(str3); 10 11 System.out.println(a); 12 System.out.println(b); 13 } 14} 15 16// output : 17// true 18// false
6、replace() 子字符串替换为其他的新的指定字符串
1public class Main { 2 public static void main(String[] args) 3 { 4 String str1="xx, jiu zhang da fa hao"; 5 String str2=str1.replace("xx","Sherry"); //将xx替换为Sherry 6 System.out.println("替换前:" + str1); 7 System.out.println("替换后:" + str2); 8 } 9} 10 11// output : 12// 替换前:xx, jiu zhang da fa hao 13// 替换后:Sherry, jiu zhang da fa hao
26.递归
解题思路
从 1 到指定数之间的所有自然数相乘的结果,
n
的阶乘为:n!=n *(n-1)*(n-2)*…… * 2 * 1
而对于(n-1)!
,则有如下表达式:(n-1)!=(n-1)*(n-2)*…… * 2 * 1
从上述两个表达式可以看到阶乘具有明显的递推性质,即符合如下递推公式:n != n *(n - 1)!
因此,可以采用递归的思想来计算阶乘。import java.util.Scanner; 3 4public class Main { 5 public static void main(String[] argv) { 6 Scanner sc = new Scanner(System.in); 7 int n = sc.nextInt(); 8 System.out.println(factorial(n)); //调用递归函数 9 } 10 11 // 递归阶乘函数 12 public static int factorial(int n) { 13 if (n == 0) { //递归出口 14 return 1; 15 } else { 16 return factorial(n - 1) * n; 17 } 18 } 19}
27.自定义异常
class MyException extends Exception { // write your code here } public class Solution { /** * @param num: The legal numbers passed in are required to be between 0 and 100, * including 0 and 100 * @throws MyException: Throwing our custom exception */ public void validate(int num) throws MyException { // write your code here } } public class Main { public static void main(String[] args) { Solution solution = new Solution(); int num = Integer.parseInt(args[0]); try { solution.validate(num); if ((num < 0) || (num > 100)) { throw new RuntimeException("You need to throw a custom exception"); } } catch (MyException e) { System.out.println(e.getMessage()); } } }
28.数组排序
import java.util.Scanner; 2import java.util.ArrayList; 3import java.util.Comparator; 4import java.util.Arrays; 5 6public class Main { 7 public static void main(String[] args) { 8 Scanner scanner1 = new Scanner(System.in); 9 int n = scanner1.nextInt(); 10 int[] a = new int[n]; 11 for (int i = 0;i<n;i++) { 12 a[i] = scanner1.nextInt(); 13 } 14 Arrays.sort(a); 15 for (int aa: a) { 16 System.out.print(aa+ " "); 17 } 18 } 19}
import java.util.Scanner; import java.util.ArrayList; import java.util.List; import java.util.Collections; import java.util.Comparator; public class Main { public static void main(String[] args) { // write your code here // read data from console Scanner sc = new Scanner(System.in); int n = sc.nextInt(); List<Integer> list = new ArrayList<>(); for(int i = 0; i < n; i++){ list.add(sc.nextInt()); } Collections.sort(list); // output the answer to the console according to the // requirements of the question for(int num : list){ System.out.print(num + " "); } } }
29.使用 final 关键字
- 对于
final
修饰的类,不可被继承。- 对于
final
修饰的方法,不可被重写。- 对于
final
修饰的变量,不可被修改。public final class Solution { 2 // write your code here 3 private final String SENTENCES = "TO BE OR NOT TO BE"; 4 5 public final void test(String name) { 6 System.out.println(name + " said: " + SENTENCES); 7 } 8}
知识要点
基本语法:final 关键字
当
final
修饰变量时,被修饰的变量必须被初始化(赋值),且后续不能修改其值,实质上是常量;
当final
修饰方法时,被修饰的方法无法被所在类的子类重写(覆写);
当final
修饰类时,被修饰的类不能被继承,并且final
类中的所有成员方法都会被隐式地指定为final
方法,但成员变量则不会变。编译期常量指的就是程序在编译时就能确定这个常量的具体值。
非编译期常量就是程序在运行时才能确定常量的值,因此也称为运行时常量。
定义上来说,声明为
final
类型的基本类型或String
类型并直接赋值(非运算)的变量就是编译期常量,即:1final int i = 4; 2final String str = "dasd";
也就是说,当
str
加上任意确定数值是,都会使得新的变量变成编译期常量。
30.ArrayList集合
ArrayList
集合的创建方式:
ArrayList<E> objectName = new ArrayList<>();
E
: 泛型数据类型,用于设置objectName
的数据类型,只能为引用数据类型。
add(E e)
此方法代表将指定的元素追加到此列表的末尾。
解法一:add() 方法
解题思路
使用集合创建的方式创建
ArrayList
对象,调用类中的添加元素方法。源代码
java
1 2import java.util.ArrayList; 3 4 5public class Solution { 6 public ArrayList<String> createList(String str1, String str2) { 7 // 创建 ArrayList 集合对象,并指定集合存储 String 类型的数据 8 ArrayList<String> list = new ArrayList<String>(); 9 // 调用 add 方法添加元素 10 list.add(str1); 11 list.add(str2); 12 13 return list; 14 } 15}
解法二:Collections 中 addAll 方法
解题思路
考虑使用集合工具类的方式向集合添加元素,在
API
中查找相应的方法。源代码
java
1 2import java.util.*; 3 4 5public class Solution { 6 public ArrayList<String> createList(String str1, String str2) { 7 // 创建集合对象,存储数据 8 ArrayList<String> list = new ArrayList<String>(); 9 Collections.addAll(list, str1, str2); 10 11 return list; 12 } 13}
知识要点
基本语法:
ArrayList<E>
ArrayList
ArrayList
类是一个可以动态修改的数组,与普通数组的区别就是它是没有固定大小的限制,我们可以添加或删除元素。ArrayList
继承了AbstractList
,并实现了List
接口。ArrayList 是一个数组队列,提供了相关的添加、删除、修改、遍历等功能。添加元素:
1bolean add(E e):将指定的元素追加到此列表的末尾 2bolean addAll(Collection<? extends E> c):按指定集合的 Iteraor 返回的顺序将指定集合中的所有元素追加到此列表的末尾
示例:
1public class Main { 2 public static void main(String args[]) { 3 ArrayList<String> list = new ArrayList<>(); 4 list.add("Hello"); 5 list.add("world"); 6 System.out.println(list); 7 } 8}
以上实例编译运行结果如下:1[Hello, world]
删除元素:
1E remove(int index):删除该列表中指定位置的元素 2boolean remove(Object o):从列表中删除指定元素的第一个出现(如果存在)
示例:
1public class Main { 2 public static void main(String args[]) { 3 ArrayList<String> list = new ArrayList<>(); 4 list.add("a"); 5 list.add("b"); 6 list.add("c"); 7 list.add("b"); 8 list.add("e"); 9 list.remove(2); 10 System.out.println(list); 11 list.remove("b"); 12 System.out.println(list); 13 } 14}
以上实例编译运行结果如下:
1[a, b, b, e] 2[a, b, e]
访问元素:
1E get(int index):返回此列表中指定位置的元素
示例:
1public class Main { 2 public static void main(String args[]) { 3 ArrayList<String> list = new ArrayList<>(); 4 list.add("a"); 5 list.add("b"); 6 list.add("c"); 7 8 System.out.println(list.get(1) + " " + list.get(2)); 9 } 10}
以上实例编译运行结果如下:
1b c
修改元素:
1E set(int index, E element):用指定的元素替换词类表中的指定位置的元素
示例:
1public class Main { 2 public static void main(String args[]) { 3 ArrayList<String> list = new ArrayList<>(); 4 list.add("a"); 5 list.add("b"); 6 list.add("c"); 7 list.set(1,"a"); 8 list.set(2,"a"); 9 System.out.println(list); 10 } 11}
以上实例编译运行结果如下:1[a, a, a]
知识要点
基本语法:
Collections
工具类
Collections
集合工具类,用来对集合进行操作。排序:
1sort(List<T> list):根据其元素的natural ordering对指定的列表进行排序。
示例:
1import java.util.*; 2 3 4class Main { 5 public static void main(String[] args) { 6 ArrayList<Integer> list = new ArrayList<Integer>(); 7 list.add(12); 8 list.add(4); 9 list.add(3); 10 list.add(5); 11 // 将集合按照默认的规则排序,按照数字从小到大的顺序排序 12 Collections.sort(list); 13 System.out.println("list = " + list); 14 } 15}
以上程序输出结果为:1list = [3, 4, 5, 12]
反转方法:
1reverse(list):
示例:1import java.util.*; 2 3 4class Main { 5 public static void main(String[] args) { 6 ArrayList<Integer> list = new ArrayList<Integer>(); 7 list.add(12); 8 list.add(4); 9 list.add(3); 10 list.add(5); 11 System.out.println("反转前:list = " + list); 12 // 将集合中的元素反转 13 Collections.reverse(list); 14 System.out.println("反转后:list = " + list); 15 } 16}
以上程序输出结果为1反转前:list = [12, 4, 3, 5] 2反转后:list = [5, 3, 4, 12]
添加元素:
1addAll(Collection<? super T> c, T... elements):将所有指定的元素添加到指定的集合。
示例:
1import java.util.*; 2 3 4class Main { 5 public static void main(String[] args) { 6 ArrayList<Integer> list = new ArrayList<Integer>(); 7 // addAll 方法可以往集合中添加元素,也可往集合中添加一个集合 8 Collections.addAll(list, 9, 20, 56); 9 System.out.println(list); 10 } 11}
以上程序输出结果为:
1[9, 20, 56]
31.数组内交换
解法一:交换数字
解题思路
要实现将数组最后一个数字与第一个数字实现交换,可以使用经典的交换三步骤实现 2 个数字的交换。
源代码
1import java.util.Scanner; 2 3public class Main { 4 public static void main(String[] args) { 5 Scanner sc = new Scanner(System.in); 6 int n = sc.nextInt(); 7 int[] array = new int[n]; 8 for (int i = 0; i < array.length; i++) { 9 array[i] = sc.nextInt(); 10 } 11 // output the answer to the console according to the 12 // requirements of the question 13 int temp = array[0]; 14 array[0] = array[array.length - 1]; 15 array[array.length - 1] = temp; 16 for (int i = 0; i < array.length; i++) { 17 System.out.print(array[i] + " "); 18 } 19 } 20}
解法二:异或运算
解题思路
可以利用异或运算 x⊕y⊕x==y 的性质来进行交换,首先让x=x⊕y,y=x⊕y,这两步执行完根据性质可知此时 y 已经变成了 x 的值,再令 x=x⊕y 可让 x 变成原来的 y。
import java.util.Scanner; 2 3public class Main { 4 public static void main(String[] args) { 5 Scanner sc = new Scanner(System.in); 6 int n = sc.nextInt(); 7 int[] array = new int[n]; 8 for (int i = 0; i < array.length; i++) { 9 array[i] = sc.nextInt(); 10 } 11 // output the answer to the console according to the 12 // requirements of the question 13 array[0] ^= array[array.length - 1]; 14 array[array.length - 1] ^= array[0]; 15 array[0] ^= array[array.length - 1]; 16 for (int i = 0; i < array.length; i++) { 17 System.out.print(array[i] + " "); 18 } 19 } 20}
^ 异或运算
- 定义:参加运算的两个数据,按二进制位进行“异或”运算。
- 运算规则:参加运算的两个对象,如果两个相应位相同为 0,相异为 1。
示例:
1int a = 26; 2int b = 11; 3int c = a ^ b;
某个二进制位在 a 和 b 中不同,结果就为 1,否则为 0。所以 26 ^ 11 = 17
126: 0 0 0 1 1 0 1 0 211: 0 0 0 0 1 0 1 1 3———————————————————— 417: 0 0 0 1 0 0 0 1
32.bug 修复之 static 关键字
静态变量属于类变量,被所有的对象所共享,在内存中只有一个副本
解法一:static 修饰成员变量
解题思路
一个类无论创建多少个实例,它的成员变量的值都是相同的,那么需要把成员变量变成随着类的加载就加载的类变量,优先级大于对象,需要使用
static
关键字。源代码
1import java.util.Random; 2 3 4public class Solution { 5 // 使用 static 关键字修饰变量,使其成为类变量,随着类的加载而存在,成为共享变量 6 static int random1 = new Random().nextInt(); 7 int random2 = new Random().nextInt(); 8}
知识要点
基本语法:静态变量
static 修饰符
static
修饰符,用来修饰类方法和类变量,被其修饰的方法叫静态方法,变量叫静态变量。无论一个类实例化多少对象,它的静态变量只有一份拷贝。 静态变量也被称为类变量。局部变量不能被声明为static
变量。static
关键字的作用是方便在没有创建对象的情况下来进行调用(方法/变量)。基本使用规则如下:
1public class Main{ 2 // 修饰成员变量 3 private static int numInstances = 0; 4 // 修饰成员方法 5 protected static int getCount() { 6 return numInstances; 7 } 8}
static 变量
static
变量也称作静态变量,静态变量和非静态变量的区别是:静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。示例:
1public class StaticDemo { 2 private static String str1 = "staticProperty"; 3 private String str2; 4 5 public StaticDemo(String str2) { 6 StaticDemo.str1 = str1; 7 this.str2 = str2; 8 } 9 10 public static void main(String[] args) { 11 // 创建 StaticDemo 对象 12 StaticDemo staticDemo = new StaticDemo("property..1"); 13 StaticDemo staticDemo1 = new StaticDemo("property..2"); 14 System.out.println(staticDemo.str1); 15 System.out.println(staticDemo.str2); 16 System.out.println(staticDemo1.str1); 17 System.out.println(staticDemo1.str2); 18 } 19}
以上实例编译运行结果如下:1staticProperty 2property..1 3staticProperty 4property..2
static 方法
static
方法一般称作静态方法,由于静态方法不依赖于任何对象就可以进行访问,因此对于静态方法来说,是没有this
的,因为它不依附于任何对象,既然都没有对象,就谈不上this
了。并且由于这个特性,在静态方法中不能访问类的非静态成员变量和非静态成员方法,因为非静态成员方法/变量都是必须依赖具体的对象才能够被调用。
但是要注意的是,虽然在静态方法中不能访问非静态成员方法和非静态成员变量,但是在非静态成员方法中是可以访问静态成员方法/变量的。示例:
1public class StaticDemo { 2 // 静态变量 3 private static String str1 = "staticProperty"; 4 // 非静态变量 5 private String str2 = "property"; 6 7 public StaticDemo() { 8 } 9 10 // 非静态方法 11 public void print1() { 12 System.out.println(str1); 13 System.out.println(str2); 14 // 非静态方法可以调用静态方法 15 print2(); 16 } 17 18 // 静态方法 19 private static void print2() { 20 System.out.println(str1); 21 // 编译直接报错,静态方法中不能访问非静态变量 22 System.out.println(str2); 23 // 编译直接报错,静态方法不能调用非静态方法 24 print1(); 25 } 26 27 public static void main(String[] args) { 28 new StaticDemo().print1(); 29 new StaticDemo().print2(); 30 } 31}
以上实例编译运行结果如下1java: 无法从静态上下文中引用非静态 变量 str2 2java: 无法从静态上下文中引用非静态 方法 print1()
static 静态代码块
静态代码块就是用
static
修饰的代码块,其特点是随着类的加载而执行,而且只执行一次。示例:
1public class StaticDemo { 2 static { 3 System.out.println("静态代码块被执行"); 4 } 5 6 void show() { 7 System.out.println("方法被执行"); 8 } 9} 10 11 12class StaticTest { 13 /** 14 * 静态代码块的特点: 15 * 随着类的加载而执行,而且只执行一次 16 */ 17 public static void main(String[] args) { 18 new StaticDemo().show(); 19 new StaticDemo().show(); 20 } 21}
以上实例编译运行结果如下:
1静态代码块被执行 2方法被执行 3方法被执行
33.去除重复数字
当你使用集合时,注意泛型不能为基本数据类型
当你需要一个不包含重复元素的集合时,
Set
是一个不错的选择HashSet
不保证集合是有序的,所以如果你的集合是有序的,可能只是一个巧合。
解法一:使用 HashSet
解题思路
由题目可知,我们需要将数组里面的无序元素去重,去除重复元素,很容易想到
Set
集合,里面的元素都是不重复的,但是HashSet
底层其实是经过hash
函数扰动来确定索引的,所以是有规律的无序排列,所以只需要将数组中的元素取出,依次放入HashSet
中,而最终要求返回一个有序数组,再将Set
集合转化为有序数组即可。import java.util.HashSet; 3import java.util.Set; 4 5 6public class Solution { 7 8 public Integer[] deDuplicate(Integer[] arr) { 9 Set<Integer> set = new HashSet<Integer>(); 10 11 for (Integer i : arr) { 12 set.add(i); 13 } 14 // 如果不定义数组大小 最终输出会出出现很多 null 15 arr = new Integer[set.size()]; 16 arr = set.toArray(arr); 17 // 需要数组是排序过的 18 Arrays.sort(arr); 19 20 return arr; 21 } 22}
解法二:使用数组索引存放
解题思路
由题目可知,数组最大不超过 10000,包含10000,所以定义的数组大小为 10000,我们先对原数组进行排序,保证其有序后,再判断
vis
数组的某个索引的位置上是否存在元素,若不存在,则将对应索引置为 1,标记为该处索引已存放元素,后依次将元素放入arr2
数组,同时计数器加一,这个是用来新建数组用的,最终将arr2
中的元素依次放入新数组中。源代码
java
1import java.util.Arrays; 2 3 4public class Solution { 5 public Integer[] deDuplicate(Integer[] arr) { 6 Integer[] vis = new Integer[10000]; 7 Integer[] arr2 = new Integer[10000]; 8 Integer top = 0; 9 Arrays.sort(arr); 10 11 // 对元素进行计数 12 int count = 0; 13 14 for (Integer i : arr) { 15 // 如果指定索引为null 证明没被放过元素 16 if (vis[i] == null) { 17 // 元素置为1 18 vis[i] = 1; 19 // 将元素依次放入 20 arr2[top++] = i; 21 count++; 22 } 23 } 24 25 Integer[] newArr = new Integer[count]; 26 27 for (int i = 0; i < count; i++) { 28 newArr[i] = arr2[i]; 29 } 30 31 return newArr; 32 } 33} 34
知识要点
基本语法:
HashSet
对于HashSet
,有以下特性:
1.HashSet
实现了 Set 接口,是基于 HashMap 来实现的,是一个不允许有重复元素的集合。2.
HashSet
允许有 null 值。3.
HashSet
是无序的,即不会记录插入的顺序。4.
HashSet
不是线程安全的, 如果多个线程尝试同时修改HashSet
,则最终结果是不确定的。 您必须在多线程访问时显式同步对HashSet
的并发访问。以下实例我们创建一个
HashSet
对象sites
,用于保存字符串元素:1HashSet<String> sites = new HashSet<String>();
添加元素
HashSet
类提供类很多有用的方法,添加元素可以使用add()
方法:1import java.util.HashSet; 2 3public class RunoobTest { 4 public static void main(String[] args) { 5 HashSet<String> sites = new HashSet<String>(); 6 sites.add("Google"); 7 sites.add("Runoob"); 8 sites.add("Taobao"); 9 sites.add("Zhihu"); 10 // 重复的元素不会被添加 11 sites.add("Runoob"); 12 System.out.println(sites); 13 } 14}
执行以上代码,输出结果如下:
1[Google, Runoob, Zhihu, Taobao]
在上面的实例中,
Runoob
被添加了两次,它在集合中也只会出现一次,因为集合中的每个元素都必须是唯一的。
删除元素
我们可以使用
remove()
方法来删除集合中的元素:1import java.util.HashSet; 2 3public class RunoobTest { 4 public static void main(String[] args) { 5 HashSet<String> sites = new HashSet<String>(); 6 sites.add("Google"); 7 sites.add("Runoob"); 8 sites.add("Taobao"); 9 sites.add("Zhihu"); 10 // 重复的元素不会被添加 11 sites.add("Runoob"); 12 // 删除元素,删除成功返回 true,否则为 false 13 sites.remove("Taobao"); 14 System.out.println(sites); 15 } 16}
执行以上代码,输出结果如下:
1[Google, Runoob, Zhihu]
HashSet 不允许存放重复值。
HashSet 是无序的,即不会记录插入的顺序。向集合中添加数据的顺序跟集合中存放数据的顺序无关,如果添加的有重复值,则集合中只能存放一个
HashSet
集合的创建方式:
HashSet<E> objectName = new HashSet<>();
E
: 泛型数据类型,用于设置objectName
的数据类型,只能为引用数据类型。
add(E e)
此方法代表将指定的元素添加到此集合(如果尚未存在)。引用数据类型的种类: - 引用数据类型包括:类(class)(例如:Integer)、接口类型(interface)、数组类型(list)、枚举类型、注解类型,字符串型(String,String的衍生类,如StringBUilder等)。
计算集合大小:
1size():返回此集合中的元素数
示例:
1import java.util.HashSet; 2 3 4public class HashSetDemo { 5 public static void main(String[] args) { 6 HashSet<Integer> hashSet = new HashSet<Integer>(); 7 hashSet.add(1); 8 hashSet.add(2); 9 hashSet.add(1); 10 hashSet.add(null); 11 System.out.println(hashSet.size()); 12 } 13}
以上实例编译运行结果如下:
13
迭代
HashSet
:可以使用
for-each
来迭代HashSet
中的元素。示例:
1import java.util.HashSet; 2 3 4public class HashSetDemo { 5 public static void main(String[] args) { 6 HashSet<Integer> hashSet = new HashSet<Integer>(); 7 hashSet.add(1); 8 hashSet.add(2); 9 hashSet.add(1); 10 hashSet.add(null); 11 12 for (Integer i : hashSet) { 13 System.out.println(i); 14 } 15 } 16}
以上实例编译运行结果如下:
1null 21 32
知识要点
基本语法:
Collections
工具类
Collections
集合工具类,用来对集合进行操作。排序:
1sort(List<T> list):根据其元素的natural ordering对指定的列表进行排序。
示例:
1import java.util.*; 2 3 4class Main { 5 public static void main(String[] args) { 6 ArrayList<Integer> list = new ArrayList<Integer>(); 7 list.add(12); 8 list.add(4); 9 list.add(3); 10 list.add(5); 11 // 将集合按照默认的规则排序,按照数字从小到大的顺序排序 12 Collections.sort(list); 13 System.out.println("list = " + list); 14 } 15}
以上程序输出结果为:
1list = [3, 4, 5, 12]
反转方法:
1reverse(list):
示例:
1import java.util.*; 2 3 4class Main { 5 public static void main(String[] args) { 6 ArrayList<Integer> list = new ArrayList<Integer>(); 7 list.add(12); 8 list.add(4); 9 list.add(3); 10 list.add(5); 11 System.out.println("反转前:list = " + list); 12 // 将集合中的元素反转 13 Collections.reverse(list); 14 System.out.println("反转后:list = " + list); 15 } 16}
以上程序输出结果为:
1反转前:list = [12, 4, 3, 5] 2反转后:list = [5, 3, 4, 12]
添加元素:
1addAll(Collection<? super T> c, T... elements):将所有指定的元素添加到指定的集合。
示例:
1import java.util.*; 2 3 4class Main { 5 public static void main(String[] args) { 6 ArrayList<Integer> list = new ArrayList<Integer>(); 7 // addAll 方法可以往集合中添加元素,也可往集合中添加一个集合 8 Collections.addAll(list, 9, 20, 56); 9 System.out.println(list); 10 } 11}
以上程序输出结果为:
1[9, 20, 56]
34. 遍历 ArrayList 集合
获取迭代器(Iterator):
Iterator<E> iterator = list.iterator();
E
:泛型数据类型,用于设置iterator
的数据类型。迭代器(Iterator)中的方法:
hasNext()
表示如果迭代具有更多元素,则返回true
。
next()
代表返回迭代中的下一个元素。
解法一:迭代器遍历
解题思路
遍历 ArrayList 集合,就是取出集合中的每一个元素,使用集合的迭代器取出集合中的元素。
源代码
1import java.util.ArrayList; 2import java.util.Iterator; 3 4 5public class Solution { 6 public void traverseList(ArrayList<String> list) { 7 Iterator<String> iterator = list.iterator(); 8 9 while (iterator.hasNext()) { 10 System.out.println(iterator.next()); 11 } 12 } 13}
解法二:普通 for 循环
解题思路
遍历 ArrayList 集合,就是取出集合中的每一个元素,循环遍历集合每一个元素。
源代码
1import java.util.ArrayList; 2 3 4public class Solution { 5 public void traverseList(ArrayList<String> list) { 6 for (int i = 0; i < list.size(); i++) { 7 System.out.println(list.get(i)); 8 } 9 } 10}
解法三:增强 for 循环
解题思路
遍历 ArrayList 集合,就是取出集合中的每一个元素,循环遍历集合每一个元素。
源代码
1import java.util.ArrayList; 2 3 4public class Solution { 5 public void traverseList(ArrayList<String> list) { 6 for (String str : list) { 7 System.out.println(str); 8 } 9 } 10}
知识要点
基本语法:Iterator
Iterator
迭代器是 java.util 包中定义的接口,实现 Interable 接口的集合必须提供一个称为 iterator 方法,该方法返回一个 Iterator 类型的对象。每个集合均可创建并返回给客户端一个实现 Interator 接口的对象,并将当前位置的概念在对象内部存储下俩。
包含的方法:
1hasNext():如果仍有元素可以迭代,则返回 true 2next():返回迭代的下一个元素 3remove():从迭代器指向的 collection 中移除迭代器返回的最后一个元素(可选操作)
示例:
1import java.util.ArrayList; 2import java.util.Iterator; 3 4 5public class Main { 6 public static void main(String[] args) { 7 ArrayList<Integer> list = new ArrayList<Integer>(); 8 list.add(1); 9 list.add(2); 10 list.add(3); 11 list.add(4); 12 13 Iterator<Integer> itr = list.iterator(); 14 15 while (itr.hasNext()) { // 判断是否还有下一项 16 17 if ((itr.next() % 2) == 0) { // 取出下一项 18 itr.remove(); // 进行删除操作 19 } 20 } 21 22 for (Integer integer : list) { 23 System.out.println(integer); 24 } 25 } 26}
以上实例编译运行结果如下:
11 23
35. 创建 HashMap 集合并添加数据
HashMap
是一个散列表,它存储的内容是键值对(key-value)
映射。
HashMap
的创建方式:
HashMap<E, E> objectName = new HashMap<E, E>();
E
: 泛型数据类型,用于设置objectName
的数据类型,只能为引用数据类型。
HashMap
中的方法:put(K key, V value)
表示
将指定的值与此映射中的指定键相关联。
解法一:put 方法
解题思路
本题要创建 HashMap 集合并添加数据,首先要使用集合对象的创建方法创建集合对象,调用添加元素的方法向集合中添加元素。
源代码
1import java.util.HashMap; 2 3 4public class Solution { 5 public HashMap<Integer, String> createHashMap(int number, String str) { 6 HashMap<Integer, String> map = new HashMap<Integer, String>(); 7 map.put(number, str); 8 9 return map; 10 } 11}
解法二:putIfAbsent 方法
解题思路
本题要创建 HashMap 集合并添加数据,首先要使用集合对象的创建方法创建集合对象,调用添加元素的方法向集合中添加元素。
源代码
1import java.util.HashMap; 2 3 4public class Solution { 5 public HashMap<Integer, String> createHashMap(int number, String str) { 6 HashMap<Integer, String> map = new HashMap<Integer, String>(); 7 map.putIfAbsent(number, str); 8 9 return map; 10 } 11}
知识要点
基本语法:HashMap
HashMap
关于 HashMap循环有以下几点说明:
- HashMap 是一个散列表,它存储的内容是键值对(key-value)映射。
- HashMap 实现了 Map 接口,根据键的 HashCode 值存储数据,具有很快的访问速度,最多允许一条记录的键为 null,不支持线程同步。
- HashMap 是无序的,即不会记录插入的顺序。
- HashMap 继承于AbstractMap,实现了 Map、Cloneable、java.io.Serializable 接口。
- HashMap 的 key 与 value 类型可以相同也可以不同,可以是字符串(String)类型的 key 和 value,也可以是整型(Integer)的 key 和字符串(String)类型的 value。
添加元素:
put(K key, V value):将键/值对添加到 hashMap 中 2putIfAbsent(K key, V value):如果 hashMap 中不存在指定的键,则将指定的键/值对插入到 hashMap 中
示例:
1import java.util.HashMap; 2 3 4public class Main { 5 public static void main(String[] args) { 6 HashMap<String, Integer> hashMap = new HashMap<String, Integer>(); 7 hashMap.put("zhangsan", 23); 8 hashMap.put("lisi", 24); 9 hashMap.put("wangwu", 25); 10 System.out.println(hashMap); 11 12 hashMap.putIfAbsent("zhaoliu", 26); 13 System.out.println(hashMap); 14 } 15}
以上代码的运行结果是:
1{lisi=24, zhangsan=23, wangwu=25} 2{lisi=24, zhaoliu=26, zhangsan=23, wangwu=25}
访问元素:
1get(Object key):获取指定 key 对应对 value 2getOrDefault(Object key, V defaultValue):获取指定 key 对应对 value,如果找不到 key ,则返回设置的默认值
示例:
1import java.util.HashMap; 2 3 4public class Main { 5 public static void main(String[] args) { 6 HashMap<String, Integer> hashMap = new HashMap<String, Integer>(); 7 hashMap.put("zhangsan", 23); 8 hashMap.put("lisi", 24); 9 hashMap.put("wangwu", 25); 10 11 System.out.println(hashMap.get("zhangsan")); 12 System.out.println(hashMap.get("lisi")); 13 System.out.println(hashMap.getOrDefault("zhaoliu", 666)); 14 } 15}
以上代码的运行结果是:
123 224 3666
删除元素:
1remove(Object key):删除 hashMap 中指定键 key 的映射关系
示例:
1import java.util.HashMap; 2 3 4public class Main { 5 public static void main(String[] args) { 6 HashMap<Integer, String> sites = new HashMap<Integer, String>(); 7 sites.put(1, "Google"); 8 sites.put(2, "LintCode"); 9 sites.put(3, "Taobao"); 10 System.out.println("HashMap: " + sites); 11 12 // 删除key为2的映射关系 13 String siteName = sites.remove(2); // return LintCode 14 System.out.println("返回值: " + siteName); 15 System.out.println("删除后的 HashMap: " + sites); 16 } 17}
以上代码的运行结果是:
1HashMap: {1=Google, 2=LintCode, 3=Taobao} 2返回值: LintCode 3删除后的 HashMap: {1=Google, 3=Taobao}
迭代 HashMap:
示例:
1import java.util.HashMap; 2 3 4public class Main { 5 public static void main(String[] args) { 6 // 创建 HashMap 对象 Sites 7 HashMap<Integer, String> Sites = new HashMap<Integer, String>(); 8 // 添加键值对 9 Sites.put(1, "Google"); 10 Sites.put(2, "LintCode"); 11 Sites.put(3, "Taobao"); 12 Sites.put(4, "Zhihu"); 13 14 // 输出 key 和 value 15 for (Integer i : Sites.keySet()) { 16 System.out.println("key: " + i + " value: " + Sites.get(i)); 17 } 18 19 // 返回所有 value 值 20 for (String value : Sites.values()) { 21 // 输出每一个value 22 System.out.print(value + ", "); 23 } 24 } 25}
以上代码的运行结果是:
1key: 1 value: Google 2key: 2 value: LintCode 3key: 3 value: Taobao 4key: 4 value: Zhihu 5Google, LintCode, Taobao, Zhihu,
36.HashMap
HashMap
是一个散列表,它存储的内容是键值对(key-value)
映射。
HashMap
中的方法:
keySet()
代表返回此地图中包含的键的Set
视图。
get(Object key)
代表返回到指定键所映射的值。
输出 HashMap 集合中所有数据的 Key 和 Value
解法一:HashMap、循环语句
解题思路
本题要输出
HashMap
集合中所有数据的Key
和Value
,我们需要使用循环语句来遍历集合中的数据通过keySet
方法来获取key
,通过get(key)
来获取值value
。源代码
1// 导入工具包中的 HashMap 2import java.util.HashMap; 3 4 5public class Solution { 6 public void printHashMap(HashMap<Integer, String> map) { 7 // 使用增强 for 循环遍历 HashMap 集合中的 key 8 for (int i : map.keySet()) { 9 System.out.println("key: " + i + "; value: " + map.get(i) + ";"); 10 } 11 } 12}
37. 鸟吃虫子
不能直接创建对象,必须使用多态的方式创建对象
当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法。
38.
在同一个类中名称相同的方法,但是这些方法的参数列表各不相同,我们将之称为方法的重载。