操作符
三元运算符
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类中自带的方法:
- toString():返回当前对象的字符串表达
- finalize():
当一个对象没有任何引用指向的时候,它就满足垃圾回收的条件。
当它被垃圾回收的时候,它的finalize() 方法就会被调用。
finalize() 不是开发人员主动调用的方法,而是由虚拟机JVM调用的。 - equals():判断两个对象的内容是否相同,不是判断地址,判断地址请用“==”
- hashCode():返回一个对象的哈希值
- 线程同步相关方法:wait()、notify()、notifyAll(),讲线程再说
- getClass():返回一个对象的类对象,反射用的多
final
- 修饰的类不能被继承
- 修饰的方法不能被重写
- 修饰的基本类型变量和引用变量只能赋值一次,不可更改
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 流有这么多分类,那我们在使用的时候应该怎么选择呢?比如什么时候用输出流?什么时候用字节流?可以根据下面三步选择适合自己的流:
- 首先自己要知道是选择输入流还是输出流。这就要根据自己的情况决定,如果想从程序写东西到别的地方,那么就选择输入流,反之就选输出流;
- 然后考虑你传输数据时,是每次传一个字节还是两个字节,每次传输一个字节就选字节流,如果存在中文,那肯定就要选字符流了。
- 通过前面两步就可以选出一个合适的节点流了,比如字节输入流 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泛型或者其父类泛型
子父类泛型转换
子类可以转父类,但子类泛型不能转父类泛型。