java查漏补缺(1)

操作符

三元运算符

int a=5<6?1:2;

Scanner

//Scanner
Scanner scanner = new Scanner(System.in);
String s = scanner.nextLine();
System.out.println(s);

条件

if—else

很简单,不提

Function接口(函数式接口)

介绍

又叫SAM类型的接口(Single Abstract Method),特征如下:

  • 使用注解@FunctionalInterface标识
  • 只包含一个抽象方法
  • 可以有多个静态方法和默认方法。
  • 默认包含Object类的方法。

函数式接口主要分为Supplier供给型函数、Consumer消费型函数、Runnable无参无返回型函数和Function有参有返回型函数。

  • Supplier的表现形式为不接受参数、只返回数据
package java.util.function;

/**
 * Represents a supplier of results.
 *
 * <p>There is no requirement that a new or distinct result be returned each
 * time the supplier is invoked.
 *
 * <p>This is a <a href="package-summary.html">functional interface</a>
 * whose functional method is {@link #get()}.
 *
 * @param <T> the type of results supplied by this supplier
 *
 * @since 1.8
 */
@FunctionalInterface
public interface Supplier<T> {

    /**
     * Gets a result.
     *
     * @return a result
     */
    T get();
}
  • Consumer消费型函数和Supplier刚好相反。Consumer接收一个参数,没有返回值
package java.util.function;

import java.util.Objects;

/**
 * Represents an operation that accepts a single input argument and returns no
 * result. Unlike most other functional interfaces, {@code Consumer} is expected
 * to operate via side-effects.
 *
 * <p>This is a <a href="package-summary.html">functional interface</a>
 * whose functional method is {@link #accept(Object)}.
 *
 * @param <T> the type of the input to the operation
 *
 * @since 1.8
 */
@FunctionalInterface
public interface Consumer<T> {

    /**
     * Performs this operation on the given argument.
     *
     * @param t the input argument
     */
    void accept(T t);

    /**
     * Returns a composed {@code Consumer} that performs, in sequence, this
     * operation followed by the {@code after} operation. If performing either
     * operation throws an exception, it is relayed to the caller of the
     * composed operation.  If performing this operation throws an exception,
     * the {@code after} operation will not be performed.
     *
     * @param after the operation to perform after this operation
     * @return a composed {@code Consumer} that performs in sequence this
     * operation followed by the {@code after} operation
     * @throws NullPointerException if {@code after} is null
     */
    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
}
  • Runnable的表现形式为即没有参数也没有返回值
package java.lang;

/**
 * The <code>Runnable</code> interface should be implemented by any
 * class whose instances are intended to be executed by a thread. The
 * class must define a method of no arguments called <code>run</code>.
 * <p>
 * This interface is designed to provide a common protocol for objects that
 * wish to execute code while they are active. For example,
 * <code>Runnable</code> is implemented by class <code>Thread</code>.
 * Being active simply means that a thread has been started and has not
 * yet been stopped.
 * <p>
 * In addition, <code>Runnable</code> provides the means for a class to be
 * active while not subclassing <code>Thread</code>. A class that implements
 * <code>Runnable</code> can run without subclassing <code>Thread</code>
 * by instantiating a <code>Thread</code> instance and passing itself in
 * as the target.  In most cases, the <code>Runnable</code> interface should
 * be used if you are only planning to override the <code>run()</code>
 * method and no other <code>Thread</code> methods.
 * This is important because classes should not be subclassed
 * unless the programmer intends on modifying or enhancing the fundamental
 * behavior of the class.
 *
 * @author  Arthur van Hoff
 * @see     java.lang.Thread
 * @see     java.util.concurrent.Callable
 * @since   JDK1.0
 */
@FunctionalInterface
public interface Runnable {
    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see     java.lang.Thread#run()
     */
    public abstract void run();
}
  • Function函数的表现形式为接收一个参数,并返回一个值。Supplier、Consumer和Runnable可以看作Function的一种特殊表现形式
package java.util.function;

import java.util.Objects;

/**
 * Represents a function that accepts one argument and produces a result.
 *
 * <p>This is a <a href="package-summary.html">functional interface</a>
 * whose functional method is {@link #apply(Object)}.
 *
 * @param <T> the type of the input to the function
 * @param <R> the type of the result of the function
 *
 * @since 1.8
 */
@FunctionalInterface
public interface Function<T, R> {

    /**
     * Applies this function to the given argument.
     *
     * @param t the function argument
     * @return the function result
     */
    R apply(T t);

    /**
     * Returns a composed function that first applies the {@code before}
     * function to its input, and then applies this function to the result.
     * If evaluation of either function throws an exception, it is relayed to
     * the caller of the composed function.
     *
     * @param <V> the type of input to the {@code before} function, and to the
     *           composed function
     * @param before the function to apply before this function is applied
     * @return a composed function that first applies the {@code before}
     * function and then applies this function
     * @throws NullPointerException if before is null
     *
     * @see #andThen(Function)
     */
    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }

    /**
     * Returns a composed function that first applies this function to
     * its input, and then applies the {@code after} function to the result.
     * If evaluation of either function throws an exception, it is relayed to
     * the caller of the composed function.
     *
     * @param <V> the type of output of the {@code after} function, and of the
     *           composed function
     * @param after the function to apply after this function is applied
     * @return a composed function that first applies this function and then
     * applies the {@code after} function
     * @throws NullPointerException if after is null
     *
     * @see #compose(Function)
     */
    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }

    /**
     * Returns a function that always returns its input argument.
     *
     * @param <T> the type of the input and output objects to the function
     * @return a function that always returns its input argument
     */
    static <T> Function<T, T> identity() {
        return t -> t;
    }
}

案例

处理抛出异常的if

ThrowExceptionFunction:

@FunctionalInterface
public interface ThrowExceptionFunction{
  void throwMessage(String message);
}

VUtils:

public class VUtils {
  public static ThrowExceptionFunction isTrue(boolean b){
    return (errorMessage)->{
      if (b){
        throw new RuntimeException(errorMessage);
      }
    };
  }
}

FunctionTest:

public class FunctionTest {
  public static void main(String[] args) {
    VUtils.isTrue(false).throwMessage("false--errorMessageInfo");//不会抛异常
    VUtils.isTrue(true).throwMessage("true--errorMessageInfo");//抛异常
  }
}
处理if分支

BranchHandle:

@FunctionalInterface
public interface BranchHandle {
  void trueOrFalseHandle(Runnable trueHandle,Runnable falseHandle);
}

VUtils:

public class VUtils {

  public static BranchHandle isTrueOrFlase(boolean b){
    return ((trueHandle, falseHandle) -> {
      if (b){
        trueHandle.run();
      }else {
        falseHandle.run();
      }
    });
  }
}

FunctionTest:

public class FunctionTest {
  public static void main(String[] args) {
    VUtils.isTrueOrFlase(false).trueOrFalseHandle(()->{
      System.out.println("trueHandle.run");
    },()->{
      System.out.println("falseHandle.fun");
    });
  }
}
如果存在值执行消费操作,否则执行基于空的操作

PresentOrElseHandler:

import java.util.function.Consumer;
@FunctionalInterface
public interface PresentOrElseHandler<T extends Object> {

  void presentOrElseHandle(Consumer<? super T> action, Runnable emptyAction);

}

VUtils:

public class VUtils {

  public static PresentOrElseHandler<?> isBlankOrNoBlank(String str){
    return (consumer, runnable) -> {
      if (str == null || str.length() == 0){
        runnable.run();
      } else {
        consumer.accept(str);
      }
    };
  }
}

FunctionTest:

public class FunctionTest {
  public static void main(String[] args) {
    VUtils.isBlankOrNoBlank("").presentOrElseHandle(System.out::println,()->{
      System.out.println("empty str");
    });
  }
}

循环

foreach

增强型for循环只能用来取值,却不能用来修改数组里的值:

//User类,下面要用
public class User {
    public int id;
    public String name;

    public User(int id, String name) {
        this.id = id;
        this.name = name;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}
	public static void foreachTest() {
        int[] ints = {1, 2, 3, 4, 5};
        for (int i : ints) {
            //无效,值传递,改变这个值并不能改变原有数组的值
            i = 1;
            System.out.println(i);
        }
        System.out.println(Arrays.toString(ints));//[1, 2, 3, 4, 5]
    }

    public static void foreachTest2() {

        ArrayList<User> users = new ArrayList<>();
        users.add(new User(1, "name1"));
        users.add(new User(2, "name2"));
        for (User i : users) {
            //无效,一开始i存的是users的地址,这样只是改变了i的地址,也和users没关系
            i = new User(3, "name3");
        }
        for (User i : users) {
            System.out.println(i);
        }
    }

    public static void foreachTest3() {

        ArrayList<User> users = new ArrayList<>();
        users.add(new User(1, "name1"));
        users.add(new User(2, "name2"));
        for (User i : users) {
            //有效,通过地址直接改变了users集合内对象的属性值。
            i.name = "updateName";
        }
        for (User i : users) {
            System.out.println(i);
        }
    }

foreach还可以遍历枚举:

public static void foreachTest4() {
		//Season枚举类见下段
        for (Season season : Season.values()) {
            System.out.println(season);
        }
    }

switch

switch是离散式判断,可以跟枚举类型:

public enum Season {
    SPRING,
    SUMMER,
    AUTUMN,
    WINTER
}
	public static void enumTest(){
        Season season = Season.SPRING;
        switch (season){
            case SPRING:
                System.out.println("spring");
                break;
            case SUMMER:
                System.out.println("summer");
                break;
            case AUTUMN:
                System.out.println("autumn");
                break;
            case WINTER:
                System.out.println("winter");
                break;
        }
    }

结束外部循环

		//用一个boolean来判断结束循环
        boolean breakOut=false;
        for (int i=0;i<5;i++){
            for (int j=0;j<5;j++){
                if (i==3){
                    breakOut=true;
                    break;
                }
                System.out.println("i:"+i+",j:"+j);
            }
            if (breakOut==true){
                break;
            }
        }
        //给外部循环起个名,指名break
        outloop:
        for (int i=0;i<5;i++){
            for (int j=0;j<5;j++){
                if (i==3){
                    break outloop;
                }
                System.out.println("i:"+i+",j:"+j);
            }
        }

继承与接口

多态

分为运算符多态和类多态。
运算符多态:比如"+"运算符可以加数字也可以拼接字符串。
类多态:同一个类的不同对象执行同一方法,结果不同。
类多态条件:
1.两个类继承同一个父类(或同一个接口),然后重写父类的方法(或实现接口方法)。
2.两个类都调用父类(或接口)的方法。
这样可以保证编写代码的时候方法调用的统一,不用根据具体类调一个具体方法。

隐藏

隐藏,就是子类继承父类后,重写了父类的静态方法。
因为静态方法和静态变量不能改变/重写,所以这里的重写实际上是替换、隐藏了父类的静态方法。

//父类
public class Hero {
    public String name;
    protected float hp;
    
    //类方法,静态方法
    //通过类就可以直接调用
    public static void battleWin(){
        System.out.println("hero battle win");
    }
}
//子类
public class ADHero extends Hero{
    //隐藏父类的battleWin方法
    public static void battleWin(){
        System.out.println("ad hero battle win");
    }
}
	public static void main(String[] args) {
        Hero h =new ADHero();
        ADHero adHero = new ADHero();
        h.battleWin();//hero battle win(执行了父类方法)
        adHero.battleWin();//ad hero battle win(执行子类自己的方法)
    }

super

实例化一个ADHero(), 其构造方法会被调用,其父类的构造方法也会被调用
父类构造方法先调用,子类构造方法会默认调用父类的无参的构造方法
当父类只有一个有参构造方法,则子类的构造器必须通过super显式调用父类的有参构造方法。

Object类

所有类继承自Object类。
Object类中自带的方法:

  1. toString():返回当前对象的字符串表达
  2. finalize():
    当一个对象没有任何引用指向的时候,它就满足垃圾回收的条件。
    当它被垃圾回收的时候,它的finalize() 方法就会被调用。
    finalize() 不是开发人员主动调用的方法,而是由虚拟机JVM调用的。
  3. equals():判断两个对象的内容是否相同,不是判断地址,判断地址请用“==”
  4. hashCode():返回一个对象的哈希值
  5. 线程同步相关方法:wait()、notify()、notifyAll(),讲线程再说
  6. getClass():返回一个对象的类对象,反射用的多

final

  1. 修饰的类不能被继承
  2. 修饰的方法不能被重写
  3. 修饰的基本类型变量和引用变量只能赋值一次,不可更改

static

static可以修饰成员变量(静态变量)、成员方法(静态方法)、代码块
静态变量/静态方法:所有该类的实例均共享
静态代码块:在类被加载时,执行一次。

接口

接口中声明的属性,只能是public static final修饰

内部类

静态内部类和非静态内部类和主类里面的属性、方法平起平坐。
匿名内部类和本地类则既可以放在主类里也可以放在主类的方法、代码块内部。

非静态内部类

public class xxx{
        class yyy{
            
        }
    }

外部类存在,才能创建内部类

new xxx().new yyy()

静态内部类

public class xxx{
        static class yyy{
            
        }
    }

不需要外部类存在,就能创建内部类

new xxx.yyy()

匿名内部类

匿名类指的是在声明一个类的同时实例化它,使代码更加简洁精练
通常情况下,要使用一个接口或者抽象类,都必须创建一个子类
有的时候,为了快速使用,直接实例化一个抽象类,并“当场”实现其抽象方法。
既然实现了抽象方法,那么就是一个新的类,只是这个类,没有命名。这样的类,叫做匿名类

public abstract class Abstract_Object {
    public abstract void abstract_method();
}
public class Main {
    public static void main(String[] args) {
        Abstract_Object object = new Abstract_Object() {
            @Override
            public void abstract_method() {
                System.out.println("abstract_method()");
            }
        };
        object.abstract_method();
    }
}

本地类

本地类可以理解为有名字的匿名类

public abstract class Abstract_Object {
    public abstract void abstract_method();
}
public class Main {
    public static void main(String[] args) {
        class NewObject extends Hero {
            public void abstract_method() {
                System.out.println("abstract_method()");
            }
        }
        NewObject object = new NewObject();
        object.abstract_method();
    }
}

默认方法

接口中可以写默认方法,实现类就可以不用重新实现了

public interface PersonMethod {
    void die();
    //接口方法的默认实现
    default public void eat(){
        System.out.println("eat()");
    }
}
public class Main {
    public static void main(String[] args) {
        //这里用个本地类来测试
        class Person implements PersonMethod{
            //eat()方法可以不用实现
            @Override
            public void die() {
                System.out.println("die");
            }
        }
        Person person = new Person();
        person.eat();
        person.die();
    }
}

异常处理

基本结构

	try{
            //todo
        }
        catch(FileNotFoundException e){
            e.printStackTrace();
        }
        finally{
            //不管有无异常,一定执行
        }

多异常处理

	try {
            //todo
        } catch (FileNotFoundException | ParseException e) {
            if (e instanceof FileNotFoundException)
                System.out.println("FileNotFoundException");
            if (e instanceof ParseException)
                System.out.println("ParseException");
            e.printStackTrace();
        }

throw与throws

throws表示该方法会把可能的异常向上层抛出,但不能总往上抛,总有一层要try、catch、finally
throw是在方法体中代码执行过程中手动抛出了异常。

 	private static void method1() {
        try {
            method2();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
    private static void method2() throws FileNotFoundException {
        throw new FileNotFoundException();
    }

异常与错误的分类

在这里插入图片描述

异常类

异常类的继承图:
在这里插入图片描述

IO流

分类

按方向分

到内存程序中,是输入流,从程序到文件啥的,是输出流。

按操作方式分

在这里插入图片描述

按操作对象分

在这里插入图片描述

选择

知道了 IO 流有这么多分类,那我们在使用的时候应该怎么选择呢?比如什么时候用输出流?什么时候用字节流?可以根据下面三步选择适合自己的流:

  1. 首先自己要知道是选择输入流还是输出流。这就要根据自己的情况决定,如果想从程序写东西到别的地方,那么就选择输入流,反之就选输出流;
  2. 然后考虑你传输数据时,是每次传一个字节还是两个字节,每次传输一个字节就选字节流,如果存在中文,那肯定就要选字符流了。
  3. 通过前面两步就可以选出一个合适的节点流了,比如字节输入流 InputStream,如果要在此基础上增强功能,那么就在处理流中选择一个合适的即可。

常见流的使用


import com.coderhao.User;
import java.io.*;
import java.security.PublicKey;

public class FileTest {
    public static void main(String[] args) {
        //相对路径
        File file = new File("a.exe");
        String path = file.getAbsolutePath();
        System.out.println(path);//在项目路径下,和src路径平行
        //绝对路径
        File file1 = new File("f:/a.exe");
        String path1 = file1.getAbsolutePath();
        System.out.println(path1);//f:\a.exe

        //字节流
        File file2 = new File("zijieliu.txt");
        //把流定义在try()里,try,catch或者finally结束的时候,会自动关闭,否则要手动关闭
        //先用哪个流就要把哪个流放前面
        try (FileOutputStream fileOutputStream = new FileOutputStream(file2)) {
            //输出
            String data = new String("hello有中文");
            byte[] bytes = data.getBytes("utf-8");
            fileOutputStream.write(bytes);

        } catch (IOException e) {
            e.printStackTrace();
        }

        try (FileInputStream fileInputStream = new FileInputStream(file2)) {
            //输入
            byte[] all = new byte[(int) file2.length()];
            fileInputStream.read(all);
            String s = new String(all, "utf-8");
            System.out.println(s);

        } catch (IOException e) {
            e.printStackTrace();
        }

        //字符流
        File file3 = new File("zifuliu.txt");
        try (FileWriter fileWriter = new FileWriter(file3)) {
            //输出字符
            String data = "字符流写出字符。";
            fileWriter.write(data);
        } catch (IOException e) {
            e.printStackTrace();
        }
        //FileReader是不能手动设置编码方式的,为了使用其他的编码方式,只能使用InputStreamReader来代替
        //并且使用new InputStreamReader(new FileInputStream(f),"utf-8"); 这样的形式
        try (InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream(file3), "utf-8")) {
            //输入字符
            char[] all = new char[(int) file3.length()];
            inputStreamReader.read(all);
            String s = new String(all);
            System.out.println(s);

        } catch (IOException e) {
            e.printStackTrace();
        }

        //缓存流
        //以介质是硬盘为例,字节流和字符流的弊端:在每一次读写的时候,都会访问硬盘。 如果读写的频率比较高的时候,其性能表现不佳。
        //缓存流在写入数据的时候,会先把数据写入到缓存区,直到缓存区达到一定的量,才把这些数据,一起写入到硬盘中去。按照这种操作模式,就不会像字节流,字符流那样每写一个字节都访问硬盘,从而减少了IO操作
        File file4 = new File("huancunliu.txt");
        //Socket编程中,尽量用PrintWriter取代BufferedWriter
        try (FileWriter fileWriter = new FileWriter(file4); PrintWriter printWriter = new PrintWriter(fileWriter)) {
            //输出
            printWriter.println("阿联军的啦aaa");
            printWriter.println("ashdkjh萨拉丁");

        } catch (IOException e) {
            e.printStackTrace();
        }

        try (FileReader fileReader = new FileReader(file4); BufferedReader bufferedReader = new BufferedReader(fileReader)) {
            //一行一行的读
            while (true) {
                String line = bufferedReader.readLine();
                if (line == null) {
                    break;
                }
                System.out.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }


        //数据流
        //使用数据流的writeUTF()和readUTF()可以进行数据的格式化顺序读写
        File file5 = new File("shujuliu.txt");
        try (FileOutputStream fileOutputStream = new FileOutputStream(file5); DataOutputStream dataOutputStream = new DataOutputStream(fileOutputStream)) {
            //输出
            dataOutputStream.writeBoolean(true);
            dataOutputStream.writeUTF("安理会是的hello");
            dataOutputStream.writeDouble(13.58);
        } catch (IOException e) {
            e.printStackTrace();
        }

        try (FileInputStream fileInputStream = new FileInputStream(file5); DataInputStream dataInputStream = new DataInputStream(fileInputStream)) {
            //数据的读写要一一对应,有顺序的
            boolean b = dataInputStream.readBoolean();
            System.out.println(b);
            String s = dataInputStream.readUTF();
            System.out.println(s);
            double v = dataInputStream.readDouble();
            System.out.println(v);

        } catch (IOException e) {
            e.printStackTrace();
        }

        //对象流,指的是可以直接把一个对象以流的形式传输给其他的介质(序列化过程)
        //只能是implements Serializable 的类的对象
        File file6 = new File("duixiangliu.txt");
        try (FileOutputStream fileOutputStream = new FileOutputStream(file6); ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream)) {
            User user1 = new User(001, "name1");
            User user2 = new User(002, "name2");
            objectOutputStream.writeObject(user1);
            objectOutputStream.writeObject(user2);

        } catch (IOException e) {
            e.printStackTrace();
        }

        try (FileInputStream fileInputStream = new FileInputStream(file6); ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream)) {
            //写两个对象也只能读开头的一个对象
            User user = (User) objectInputStream.readObject();
            System.out.println(user);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
        //追加
        //以上写入都是覆盖,如果要追加,可以1.改变文件指针 2.创建写入对象时第二个参数为true
        File file7 = new File("zhuijia.txt");
        for (int i = 0; i < 5; i++) {
            appendTest(file7);
        }
        try (FileReader fileReader = new FileReader(file7); BufferedReader bufferedReader = new BufferedReader(fileReader)) {


            while (true) {
                String s = bufferedReader.readLine();
                if (s == null) {
                    break;
                }
                System.out.println(s);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void appendTest(File file) {
        //打开一个写文件器,构造函数中的第二个参数true表示以追加形式写文件
        try (FileOutputStream fileOutputStream = new FileOutputStream(file, true); PrintWriter printWriter = new PrintWriter(fileOutputStream)) {
            printWriter.print("start中英文结合end");
            printWriter.print(12.55);
            //强制把缓存中的数据写入硬盘,无论缓存是否已满
            printWriter.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

数组

		int[] oldArray=new int[]{3,2,1,5,4};
        int[] newArray=new int[oldArray.length];

        //复制数组
        System.arraycopy(oldArray,0,newArray,0,oldArray.length);
        System.out.println(Arrays.toString(newArray));

        //数组自带快速排序
        Arrays.sort(newArray);
        System.out.println(Arrays.toString(newArray));

        //二分搜索,需事先排序,若有相同元素,结果不确定
        int i = Arrays.binarySearch(newArray, 3);


        //两个数组是否相等
        boolean equals = Arrays.equals(oldArray, newArray);
        System.out.println(equals);

        //填充
        Arrays.fill(newArray,3);
        System.out.println(Arrays.toString(newArray));

char

		Character c='a';
        System.out.println(c);

        System.out.println(Character.isLetter('a'));//判断是否为字母
        System.out.println(Character.isDigit('a')); //判断是否为数字
        System.out.println(Character.isWhitespace(' ')); //是否是空白
        System.out.println(Character.isUpperCase('a')); //是否是大写
        System.out.println(Character.isLowerCase('a')); //是否是小写
        System.out.println(Character.toUpperCase('a')); //转换为大写
        System.out.println(Character.toLowerCase('A')); //转换为小写

数字与string的转换

		String num = "12.7";
        //数字与字符串的转化
        double v = Double.parseDouble(num);
        String s = String.valueOf(v);
        System.out.println(v+"|"+s);
        //四舍五入
        long round = Math.round(v);
        System.out.println(round);
        //随机数[0,1)
        double random = Math.random();
        System.out.println(random);
        //开方
        double sqrt = Math.sqrt(8);
        System.out.println(sqrt);
        //次方
        double pow = Math.pow(2, 5);
        System.out.println(pow);
        //PI
        System.out.println(Math.PI);
        //自然常数e
        System.out.println(Math.E);
        //小数点后保留两位
        System.out.printf("%.2f%n",Math.PI);

string

		//这些操作都不会改变原有的字符串,只是返回一个新字符串
        String s="中,English,UP,low";
        //String s="中,";
        System.out.println(s.length());
        System.out.println(s.charAt(0));
        char[] chars = s.toCharArray();
        //截取,左闭右开
        System.out.println(s.substring(1));
        System.out.println(s.substring(1,s.length()));
        //分割
        String[] strings = s.split(",");
        for (String s1:strings){
            System.out.print(s1+"-");
        }
        System.out.println();
        //去掉首尾空格
        s="   "+s+"  ";
        s= s.trim();
        System.out.println(s);
        //大小写
        System.out.println(s.toLowerCase());
        System.out.println(s.toUpperCase());
        //出现位置
        System.out.println(s.indexOf(","));
        System.out.println(s.contains("Eng"));
        //替换
        System.out.println(s.replaceAll(",","-"));
        System.out.println(s.replaceFirst(",","-"));
        //是否以xx开始和结束
        System.out.println(s.startsWith("中"));
        System.out.println(s.endsWith("w"));

        //StringBuffer
        StringBuffer sb = new StringBuffer(s);
        System.out.println(sb);
        //追加插入删除反转
        sb.append("append");
        System.out.println(sb);
        sb.insert(0,"insert");
        System.out.println(sb);
        //删除左闭右开
        sb.delete(0,5);
        System.out.println(sb);
        sb.reverse();
        System.out.println(sb);
        System.out.println(sb.length());
        System.out.println(sb.capacity());

日期

		Date now = new Date();
        System.out.println(now);
        //从1970年开始的毫秒数
        System.out.println(now.getTime());
        System.out.println(new Date(0));
        //格式化
        //date->String
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
        String formatDate = sdf.format(now);
        System.out.println(formatDate);
        //String->date
        try {
            Date d2 = sdf.parse(formatDate);
            System.out.println(d2);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        //日历
        Calendar c = Calendar.getInstance();
        Date d3 = c.getTime();
        System.out.println(d3);
        //翻日历
        c.add(Calendar.YEAR,2);
        c.add(Calendar.MONTH,-1);
        System.out.println(c.getTime());

集合

集合继承图

数组式的查找快,链表式的增删快,二叉树式的排序快,hash式的查找、增删都快。
HashSet无序,list有序。
在这里插入图片描述

常见使用

import com.coderhao.object.User;
import java.util.*;

public class CollectionTest {
    public static void main(String[] args) {

        ArrayList<User> users = new ArrayList<>();
        users.add(new User(001, "name1"));
        users.add(new User(002, "name2"));

        //迭代器iterator的for写法
        for (Iterator<User> iterator = users.iterator(); iterator.hasNext(); ) {
            User next = iterator.next();
            System.out.println(next);

        }

        //除了实现了List接口外,LinkedList还实现了双向链表结构Deque,可以很方便的在头尾插入删除数据
        final LinkedList<User> linkedList = new LinkedList<>();
        //尾部添加
        linkedList.add(new User(1, "name1"));
        //头部添加
        linkedList.addFirst(new User(0, "name-first"));
        System.out.println(linkedList);
        //查看头部
        System.out.println(linkedList.getFirst());
        //移除头部
        System.out.println(linkedList.removeFirst());
        System.out.println(linkedList);
        //LinkedList 除了实现了List和Deque外,还实现了Queue接口(队列)。Queue是先进先出队列FIFO
        //offer 在最后添加元素,poll 取出第一个元素,peek 查看第一个元素
        linkedList.offer(new User(2, "name2"));
        System.out.println(linkedList);
        //poll取出和remove类似
        System.out.println(linkedList.poll());
        System.out.println(linkedList);
        //peek查看不会移除
        System.out.println(linkedList.peek());
        System.out.println(linkedList);

        //与FIFO(先入先出的)队列类似的一种数据结构是FILO先入后出栈Stack
        //push放入栈顶,peek查看栈顶,pop取出栈顶
        class StackTest extends Stack {
        }

        //二叉树
        class Node {
            // 左子节点
            public Node leftNode;
            // 右子节点
            public Node rightNode;
            // 值
            public Object value;

            // 插入 数据
            public void add(Object v) {
                // 如果当前节点没有值,就把数据放在当前节点上
                if (null == value)
                    value = v;
                    // 如果当前节点有值,就进行判断,新增的值与当前值的大小关系
                else {
                    // 新增的值,比当前值小或者相同
                    if ((Integer) v - ((Integer) value) <= 0) {
                        if (null == leftNode)
                            leftNode = new Node();
                        leftNode.add(v);
                    }
                    // 新增的值,比当前值大
                    else {
                        if (null == rightNode)
                            rightNode = new Node();
                        rightNode.add(v);
                    }
                }
            }

            // 中序遍历所有的节点
            public List<Object> values() {
                List<Object> values = new ArrayList<>();

                // 左节点的遍历结果
                if (null != leftNode)
                    values.addAll(leftNode.values());
                // 当前节点
                values.add(value);
                // 右节点的遍历结果
                if (null != rightNode)
                    values.addAll(rightNode.values());
                return values;
            }
        }
        int[] ints = {2, 31, 24, 65, 23, 43};
        Node root = new Node();
        for (int i : ints) {
            root.add(i);
        }
        List<Object> values = root.values();
        System.out.println(values);//[2, 23, 24, 31, 43, 65]

        //HashMap要比List效率高,这是一种用空间换时间的思维方式得到的结果
        //Set中元素没顺序,HashSet底层就是HashMap,只是不用HashMap的v,只用k来存数据。

        //排序
        ArrayList<User> list = new ArrayList<>();
        list.add(new User(12, "name12"));
        list.add(new User(18, "name18"));
        list.add(new User(7, "name7"));
        Comparator<User> userComparator = new Comparator<User>() {
            @Override
            public int compare(User o1, User o2) {
                //升序排列
                if (o1.id > o2.id) {
                    return 1;
                } else {
                    return -1;
                }
            }
        };
        Collections.sort(list, userComparator);
        System.out.println(list);

        //聚合操作lambda
        //通过聚合操作找出来id第三高的user名称
        String s = list
                .stream()
                .sorted((h1, h2) -> h1.id > h2.id ? -1 : 1)
                .skip(2)
                .map(h -> h.name)
                .findFirst()
                .get();
        System.out.println(s);
    }
}

ArrayList

		List list = new ArrayList();
		//List list = new LinkedList();
        for (int i=1;i<5;i++){
            list.add(i);
        }
        System.out.println(list);

        //add
        list.add(0,0);
        System.out.println(list);
        //contains,是否是同一个地址,而不是是否值相同
        System.out.println(list.contains(0));

        System.out.println(list.get(3));
        System.out.println(list.indexOf(4));

        //remove
        list.remove(4);
        System.out.println(list);
        //set
        list.set(3,31);
        System.out.println(list);
        //size
        System.out.println(list.size());
        //转为数组
        Integer[] array = (Integer[]) list.toArray(new Integer[]{});
        System.out.println(Arrays.toString(array));

        //addAll
        List list1 = new ArrayList();
        for (int i=5;i<7;i++){
            list1.add(i);
        }
        list.addAll(list1);
        System.out.println(list);

        //clear
        list.clear();
        System.out.println(list);

hashMap

		HashMap<Object, Object> map = new HashMap<>();
        map.put("k1","v1");
        System.out.println(map);
        System.out.println(map.get("k1"));
        map.remove("k1");
        System.out.println(map);

collections工具类

		//初始化集合numbers
        List<Integer> numbers = new ArrayList<>();

        for (int i = 0; i < 10; i++) {
            numbers.add(i);
        }
        //反转
        Collections.reverse(numbers);
        System.out.println(numbers);
        //乱序
        Collections.shuffle(numbers);
        System.out.println(numbers);
        //排序
        Collections.sort(numbers, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1-o2;
            }
        });
        System.out.println(numbers);
        //交换
        Collections.swap(numbers,0,5);
        System.out.println(numbers);
        //右移2
        Collections.rotate(numbers,2);
        System.out.println(numbers);
        //转为线程安全
        List<Integer> list = Collections.synchronizedList(numbers);
        System.out.println(list);

set

		HashSet<Integer> numberSet1 =new HashSet<Integer>();
        //HashSet中的数据不是按照插入顺序存放
        numberSet1.add(88);
        numberSet1.add(8);
        numberSet1.add(888);
        System.out.println(numberSet1);

        LinkedHashSet<Integer> numberSet2 =new LinkedHashSet<Integer>();
        //LinkedHashSet中的数据是按照插入顺序存放
        numberSet2.add(88);
        numberSet2.add(8);
        numberSet2.add(888);
        System.out.println(numberSet2);
        
        TreeSet<Integer> numberSet3 =new TreeSet<Integer>();
        //TreeSet 中的数据是进行了从小到大排序的
        numberSet3.add(88);
        numberSet3.add(8);
        numberSet3.add(888);
        System.out.println(numberSet3);
        
        //set转为数组
        Integer[] array = numberSet3.toArray(new Integer[]{});
        System.out.println(Arrays.toString(array));

注:lambda中的聚合操作

管道原:
把Collection切换成管道源很简单,调用stream()就行了。heros.stream()
但是数组却没有stream()方法,需要使用Arrays.stream(hs)
中间操作:
在这里插入图片描述
结束操作:
在这里插入图片描述

泛型

泛型

//泛型
public class FanxingTest<T> {
    LinkedList<T> values = new LinkedList<T>();

    public T getT(int index) {
        return values.get(index);
    }

    public void addT(T t) {
        values.add(t);
    }

    public static void main(String[] args) {
        FanxingTest<User> users = new FanxingTest<>();
        users.addT(new User(1, "name1"));
        System.out.println(users.getT(0));
    }
}

<? extends T>泛型

表示这是一个T泛型或者其子类泛型
该类的对象,一定是能转成T的

<? super T>泛型

表示这是一个T泛型或者其父类泛型

子父类泛型转换

子类可以转父类,但子类泛型不能转父类泛型。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值