Java学习_对之前内容进行复习
1.1 StringBuffer,StringJoiner类和String.join方法使用
package com.fjnu.Review;
import java.util.StringJoiner;
/**
*
* 拼接字符串:Hello Bob, Alice, Grace!
*
* @author 23287
*/
public class StringJoinerTest {
public static void main(String[] args) {
/**
* 使用StringBuffer
*/
String[] strings = {"Bob", "Alice", "Grice"};
StringBuffer stringBuffer = new StringBuffer("Hello");
for(String string : strings){
stringBuffer.append(" ");
stringBuffer.append(string);
stringBuffer.append(",");
}
stringBuffer.replace(stringBuffer.length()-1,stringBuffer.length(),"!");
System.out.println(stringBuffer);
/**
* 使用StringJoiner
*/
StringJoiner stringJoiner = new StringJoiner(", ", "Hello ", "!");
for(String string : strings){
stringJoiner.add(string);
}
System.out.println(stringJoiner);
/**
*
* 用String.join()方法
*
*/
String string2 = String.join(", ",strings);
System.out.println(string2);
}
}
1.2异常
1.2.1运行时异常看具体情况,编译时异常必须处理
1.2.2自定义异常
自定义异常一般需要自定义一个BaseException作为“根异常”,通常建议从RuntimeException派生
public class BaseException extends RuntimeException {
}
public class UserNotFoundException extends BaseException {
}
public class LoginFailedException extends BaseException {
}
自定义的BaseException应该提供多个构造方法:
public class BaseException extends RuntimeException {
public BaseException() {
super();
}
public BaseException(String message, Throwable cause) {
super(message, cause);
}
public BaseException(String message) {
super(message);
}
public BaseException(Throwable cause) {
super(cause);
}
}
以上类似于RuntimeExeception类构造方法
1.3反射
练习使用Class Field Method Constructor这几个类
1.4注解
1.5泛型
1.6集合
1.6.1 Collection
1.List
需要增删元素的有序列表,我们使用最多的是ArrayList。
List中的contains方法中用equals方法实现。
编写equals()方法如下:
public boolean equals(Object o) {
if (o instanceof Person) {
Person p = (Person) o;
return this.name.equals(p.name) && this.age == p.age;
}
return false;
}
使用Iterator迭代器遍历,Java的for each循环本身就使用Iterator遍历
2.Set
Set接口并不保证有序,而SortedSet接口则保证元素是有序的:
HashSet是无序的,因为它实现了Set接口,并没有实现SortedSet接口;
TreeSet是有序的,因为它实现了SortedSet接口。
使用TreeSet和使用TreeMap的要求一样,添加的元素必须正确实现Comparable接口,如果没有实现Comparable接口,那么创建TreeSet时必须传入一个Comparator对象。
1.6.2 Map
put get方法
遍历Map可以使用foreach或者entrySet
public class Main {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
map.put("apple", 123);
map.put("pear", 456);
map.put("banana", 789);
for (Map.Entry<String, Integer> entry : map.entrySet()) {
String key = entry.getKey();
Integer value = entry.getValue();
System.out.println(key + " = " + value);
}
}
}
在Map的内部,对key做比较是通过equals()实现的,这一点和List查找元素需要正确覆写equals()是一样的,即正确使用Map必须保证:作为key的对象必须正确覆写equals()方法。
正确使用Map必须保证:
作为key的对象必须正确覆写equals()方法,相等的两个key实例调用equals()必须返回true;
作为key的对象还必须正确覆写hashCode()方法,且hashCode()方法要严格遵循以下规范:
如果两个对象相等,则两个对象的hashCode()必须相等;
如果两个对象不相等,则两个对象的hashCode()尽量不要相等。
equals()用到的用于比较的每一个字段,都必须在hashCode()中用于计算;equals()中没有使用到的字段,绝不可放在hashCode()中计算。
在冲突的时候,一种最简单的解决办法是用List存储hashCode()相同的key-value。
TreeMap中当key的类是自定义的时,需要实现Comparable接口,或者传入Comparator。
用Properties读取配置文件,一共有三步:
创建Properties实例;
调用load()读取文件;
调用getProperty()获取配置。
如果通过setProperty()修改了Properties实例,可以把配置写入文件,以便下次启动时获得最新配置。写入配置文件使用store()方法:
Properties props = new Properties();
props.setProperty("url", "http://www.liaoxuefeng.com");
props.setProperty("language", "Java");
props.store(new FileOutputStream("C:\\conf\\setting.properties"), "这是写入的properties注释");
1.6.3
List.of()函数构成的是只读List
对于具体的实现类,有的Queue有最大队列长度限制,有的Queue没有。注意到添加、删除和获取队列元素总是有两个方法,这是因为在添加或获取元素失败时,这两个方法的行为是不同的。我们用一个表格总结如下: |
---|
throw Exception |
添加元素到队尾 |
取队首元素并删除 |
取队首元素但不删除 |
LinkedList即实现了List接口,又实现了Queue接口,但是,在使用的时候,如果我们把它当作List,就获取List的引用,如果我们把它当作Queue,就获取Queue的引用:
// 这是一个List:
List<String> list = new LinkedList<>();
// 这是一个Queue:
Queue<String> queue = new LinkedList<>();
PriorityQueue和Queue的区别在于,它的出队顺序与元素的优先级有关,对PriorityQueue调用remove()或poll()方法,返回的总是优先级最高的元素。
要使用PriorityQueue,我们就必须给每个元素定义“优先级”。
我们放入的顺序是"apple"、"pear"、"banana",但是取出的顺序却是"apple"、"banana"、"pear",这是因为从字符串的排序看,"apple"排在最前面,"pear"排在最后面。
因此,放入PriorityQueue的元素,必须实现Comparable接口,PriorityQueue会根据元素的排序顺序决定出队的优先级。
如果我们要放入的元素并没有实现Comparable接口怎么办?PriorityQueue允许我们提供一个Comparator对象来判断两个元素的顺序。
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Queu
e;public class Main {
public static void main(String[] args) {
Queue<User> q = new PriorityQueue<>(new UserComparator());
// 添加3个元素到队列:
q.offer(new User("Bob", "A1"));
q.offer(new User("Alice", "A2"));
q.offer(new User("Boss", "V1"));
System.out.println(q.poll()); // Boss/V1
System.out.println(q.poll()); // Bob/A1
System.out.println(q.poll()); // Alice/A2
System.out.println(q.poll()); // null,因为队列为空
}
}
class UserComparator implements Comparator<User> {
public int compare(User u1, User u2) {
if (u1.number.charAt(0) == u2.number.charAt(0)) {
// 如果两人的号都是A开头或者都是V开头,比较号的大小:
return u1.number.compareTo(u2.number);
}
if (u1.number.charAt(0) == 'V') {
// u1的号码是V开头,优先级高:
return -1;
} else {
return 1;
}
}
}
class User {
public final String name;
public final String number;
public User(String name, String number) {
this.name = name;
this.number = number;
}
public String toString() {
return name + "/" + number;
}
}
Queue是队列,只能一头进,另一头出。
如果允许两头都进,两头都出,这种队列叫双端队列(Double Ended Queue),学名Deque。
Deque是一个接口,它的实现类有ArrayDeque和LinkedList。
我们发现LinkedList真是一个全能选手,它即是List,又是Queue,还是Deque。但是我们在使用的时候,总是用特定的接口来引用它,这是因为持有接口说明代码的抽象层次更高,而且接口本身定义的方法代表了特定的用途。
Queue | Deque | |
---|---|---|
添加元素到队尾 | add(E e)/ offer(E e) | addLast(E e)/ offerLast(E e) |
取队首元素并删除 | E remove() / E poll() | E removeFirst() / E pollFirst() |
取队首元素但不删除 | E element() / E peek() | E getFirst() / E peekFirst() |
添加元素到队首 | 无 | addFirst(E e) / offerFirst(E e) |
取队尾元素并删除 | 无 | E removeLast() / E pollLast() |
取队尾元素但不删除 | 无 | E getLast() / E peekLast() |
Stack只有入栈和出栈的操作:
把元素压栈:push(E);
把栈顶的元素“弹出”:pop(E);
取栈顶元素但不弹出:peek(E)。
在Java中,我们用Deque可以实现Stack的功能:当我们把Deque作为Stack使用时,注意只调用push()/pop()/peek()方法,不要调用addFirst()/removeFirst()/peekFirst()方法,这样代码更加清晰。
1.6.4使用Iterator
package com.fjnu.Review;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class IteratorTestPlus {
public static void main(String[] args) {
ReverseList<String> rlist = new ReverseList<>();
rlist.add("Apple");
rlist.add("Orange");
rlist.add("Pear");
for (String s : rlist) {
System.out.println(s);
}
}
}
class ReverseList<T> implements Iterable<T> {
private List<T> list = new ArrayList<>();
public void add(T t){
list.add(t);
}
@Override
public Iterator<T> iterator() {
return new ReverseIterator(list.size());
}
private class ReverseIterator implements Iterator<T> {
int index;
public ReverseIterator(int size) {
this.index = size;
}
@Override
public boolean hasNext() {
return index > 0;
}
@Override
public T next() {
index--;
return ReverseList.this.list.get(index);
}
}
}