每一天的每一分每一秒都不晚!       2021年3月16日 23:18:07       

桐君过客

大三

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);
        }
    }
}

1.6.5使用Collections

posted @ 2021-03-16 23:16  桐君过客  阅读(69)  评论(0编辑  收藏  举报