Java基础学习整理

第一章:基础语法整理

String拼接

/*
 ... 
*/
int a=10,b=20;
//以下两条代码输出结果均为String类型
System.out.println(""+a+b);
//输出1020
System.out.println(a+b+"");
//输出30

Scanner用法

  1. 获取系统输入流:new scanner(System.in)

  2. 判断输入截止:hasNext()/hasNextLine

  3. 获取用户输入信息:scanner.next()/scanner.nextLine()

  4. 关闭scanner方法:scanner.close()

    完整代码如下所示:

    import java.util.Scanner;
    
    public class InputScnner {
        public static void main(String[] args) {
            System.out.println("please input a string:");
    
            //Java-Scnner输入流
            Scanner scanner = new Scanner(System.in);
    	   /*
    	      next方法:
     	1.只有在遇到有效字符才正式生效,即开始输入的若干空格字符不被正常识别记录
     	2.有效字符之后遇到空格的元素被剔除
     	3.以Enter作为截止输入符
            */
            //next() 
            if(scanner.hasNext()){
                String str = scanner.next();
                System.out.println("output is "+str);
            }
    	   /*
    		nextLine方法:
    		1.以Enter作为截止输入符
    		2.即Enter之前的所有的符号均可被正常识别记录
            */
            //nextLine() 
            if(scanner.hasNextLine()){
                String str = scanner.nextLine();
                System.out.println("output is "+str);
            }
            //close scnner
            scanner.close();
        }
    }
    

switch case穿透

switch-case匹配结构中,若case分支不存在break语句且当前条件匹配该case,则直接执行此case及之后所有case分支语句,直到遇到下一个break停止执行,代码示例如下:

/*
 如果当前I1值为B,则匹配第二个case语句,程序整体输出B所在case语句之后所有sout语句,
 直至遇到break为止,若D所在case语句也不存在break,则default语句依旧被输出。
 输出结果为:
 Nice!
 ohyeah!
 shit!
*/
switch (I1){
            case "A":
                System.out.println("Good!");
                break;
            case "B":
                System.out.println("Nice!");

            case "C":
                System.out.println("ohyeah!");
                
            case "D":
                System.out.println("shit!");
                break;
            default:
                System.out.println("Wrong!");
        }

值传递和引用传递

//值传递
public class Test {    
    public static void main(String[] args) {
        int a = 1;
        System.out.println(a);//输出 a = 1
        Test.change(a);
        System.out.println(a);//输出 a = 1
    }
    public static void change(int a){
        a = 10;
    }
}
//引用传递
public class Test {
    public static void main(String[] args) {
        Person person = new Person();
        person.name = "lisi";
        System.out.println(person.name);//输出 lisi
        Test.change(person);
        System.out.println(person.name);//输出 zhangsan
    }
    public static void change(Person person){
        person.name = "zhangsan";
    }
}
class Person{
    String name;
}

可变参数

  1. JDK 1.5新增功能
  2. 在方法声明中,在指定参数类型后添加省略号(...)
  3. 一个方法中只能声明一个可变参数,它必须是方法的最后一个参数,任何其他普通参数均需在其之前声明。
public class Exchange {
    public static void main(String[] args) {
        printMaxmum(1.2,323,12,44,4.5);
        printMaxmum(new double[]{1,3,7.7,6});
    }
  	//可变参数
    public static void printMaxmum(double... number){
        if(number.length==0)
        {
            System.out.println("no number");
            return;
        }
        double max = number[0];

        for (int i = 0; i < number.length; i++)
        {
            if (number[i]>max)
                max=number[i];
        }
        System.out.println("the max value is :"+max);
    }
}

增强for循环

int[] arrays_one = {1,2,3,4,5};
int[][] arrays_two = {{1,2},{2,3},{3,4},{4,5}};
//JDK1.5新增功能
//一维数组
for (int array:arrays_one)
{
  System.out.println(array);
}
//二维数组
for(int[] ints:arrays_two)
{
  for(int anInt:ints)
    System.out.println(anInt);
}

稀疏数组

import java.util.Scanner;

public class Test {

    public static void main(String[] args) {
        //二维数组创建
        System.out.println("please input matrix's nums,lins and cows:");
        Scanner scanner = new Scanner(System.in);
        int sum = scanner.nextInt();//有效值总数
        int lin = scanner.nextInt();//行数
        int cow = scanner.nextInt();//列数
				//初始化二维数组
        int[][] arrays_two = new int[lin][cow];
        for (int i = 0; i < sum; i++) {
            System.out.println("please input the value and its position: ");
            int num_v = scanner.nextInt();//元素值
            int lin_l = scanner.nextInt();//对应的行数
            int cow_c = scanner.nextInt();//对应的列数

            arrays_two[lin_l-1][cow_c-1] = num_v;
        }
				//输出二维数组
        for (int[] ints : arrays_two) {
            for (int anInt : ints) {
                System.out.print(anInt+"\t");
            }
            System.out.println();
        }
        /*
        初始化稀疏数组,其中行数为有效数字个数+1,列数固定3列
        其中第一行存放稀疏数组的有效值个数,行数,列数
        其余行存放对应的有效值以及其行列数
        */
        int[][] arrays_xishu = new int[sum+1][3];
        arrays_xishu[0][0] = sum;
        arrays_xishu[0][1] = arrays_two.length;
        arrays_xishu[0][2] = arrays_two[0].length;
        //遍历原数组,将有效值存放于稀疏数组中
        int count = 0;
        for (int i = 0; i < arrays_two.length; i++) {
            for (int j = 0; j < arrays_two[i].length; j++) {
                if(arrays_two[i][j]!=0)
                {
                    count += 1;
                    arrays_xishu[count][0] = arrays_two[i][j];
                    arrays_xishu[count][1] = i+1;
                    arrays_xishu[count][2] = j+1;
                }
            }
        }
        //
        System.out.println("稀疏数组如下所示:");
        for (int[] ints : arrays_xishu) {
            for (int anInt : ints) {
                System.out.print(anInt+"\t");
            }
            System.out.println();

        }
        scanner.close();
    }
}

第二章:面向对象思想

面向对象和类

  • 构造函数

    • 必须和类名一样,且没有返回值。
    • new 本质是在调用构造方法,初始化对象的值。
    • 定义有参构造之后,若想使用无参构造,需显示定义一个无参构造。
  • 析构函数

    Java不存在析构函数,Java具有内存回收机制,当变量退出其生命周期时,JVM会自动识别并调用垃圾回收器GC。

  • Java类访问权限

    同一个类 同一个包 不同包的子类 不同包的非子类
    private
    default
    protected
    public

封装

遵循原则:高内聚,低耦合

  • 保护属性信息:类的成员属性是私有的private
    • 获取类成员属性可以使用getter & setter 方法,对应IDEA工具 mac快捷键:command+return;windows快捷键:alt+inter
  • 公开行为信息:类的方法是公有的public
  • this关键字
    • this负责指向本类中的成员变量
    • this负责指向本类中的成员方法
    • this可以代替本类的构造函数
  • this示例
//OO类声明
public class OOExample {

    public static void main (String[] args)
    {
       gets obj = new gets(5);  
       System.out.println(obj.sum());
    }
    
}
//gets类声明
public class gets {
    //设定私有变量
    private int m,n;
    //类的构造函数
    public gets(int m){
        this(m,0);
    }
    public gets(int m,int n){
        this.m=m;
        this.n=n;
    }
    //定义sum方法调用add方法
    public int sum()
    {
        return this.add(m,n);//可省略this因为不会引起歧义
    }
    public int add(int m,int n)
    {
        return m+n;
    }

}

继承

  • 继承是类与类之间的一种关系,除此之外,类与类之间还可以存在依赖、组合、聚合等关系。

  • 继承关系的两个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字extendes

  • Java中类只有单继承,没有多继承,其中object类是所有类的父类。

super关键字

//父类
public class Person{
    public Person() {
        System.out.println("Person无参构造");
    }
    protected String name = "zhangsan";
}
//子类
public class Student extends Person {
   	public Student() {
      	//!!默认隐藏调用父类的!无参!构造函数!!
      	//如果调用有参构造函数,需显示声明super()方法
      	//super();
        System.out.println("Student无参构造");
    }
    private String name = "bushizhangsan";
    public void test(String name){
        System.out.println(name);//输出当前name
        System.out.println(this.name);//输出当前类对应的name
        System.out.println(super.name);//输出父类对应的name
    }
}
//主方法
public class Main {
    public static void main(String[] args) {
        Student student = new Student();
        student.test("张三");
    }
}
//程序输出
Person无参构造
Student无参构造
张三
bushizhangsan
zhangsan

方法重写

  1. 方法名必须相同,参数列表必须相同。
  2. 修饰符:继承子类属性的范围相较父类属性可以扩大,但不可以缩小:public>protected>default>private
  3. 抛出异常范围:可以被缩小,但不可以被扩大:ClassNotFoundException --> Exception(大)
  4. 重写前后子类方法名必须和父类一致,但是方法体可以不同。
  • 静态方法重写

    //父类
    public class Person{
        public static void test(){
            System.out.println("Person=>test");
        }
    }
    //子类
    public class Student extends Person {
        public static void test(){
            System.out.println("Student=>test");
        }
    }
    //主方法
    public class Main {
        public static void main(String[] args) {
            Student student = new Student();
            student.test();
            Person person = new Student();//延伸创建父类对象
            person.test();
        }
    }
    //输出结果
    Student=>test
    Person=>test
    
  • 非静态方法重写

    //父类
    public class Person{
        public void test(){
            System.out.println("Person=>test");
        }
    }
    //子类
    public class Student extends Person {
      	@Override//注解:有功能的注释
        public void test(){
            System.out.println("Student=>test");
        }
    }
    //主方法
    public class Main {
        public static void main(String[] args) {
            Student student = new Student();
            student.test();
            Person person = new Student();//重写父类方法
            person.test();
        }
    }
    //输出结果
    Student=>test
    Student=>test
    

多态

  • 多态即同一种对象可以根据发送对象的不同而采取多种不同的行为方式,即对函数而言,取决于左部类型信息。

  • 多态存在条件:有继承关系、子类重写父类方法、父类引用子类对象。

  • 多态本质是父类引用指向子类的对象,子类转换为父类,向上转型;父类转换为子类,向下转型,须强制转换。

static关键词

  • static静态代码块

    public class Person{
      	//1.随类加载时一同执行,且只执行一次
        static {
            System.out.println("静态代码块");
        }
      	//2.完成类的初始操作
        {
            System.out.println("匿名代码块");
        }
      	//3.当类的初始操作完成后执行构造方法
        public Person(){
            System.out.println("构造方法");
        }
    
        public static void main(String[] args) {
            Person person = new Person();
            System.out.println("===============");
            Person person2 = new Person();
    
        }
    }
    //输出结果
    静态代码块
    匿名代码块
    构造方法
    ===============
    匿名代码块
    构造方法
    
  • static静态导入包

    import static java.lang.Math.random;
    public class Person{
        {
            System.out.println("匿名代码块");
        }
        static {
            System.out.println("静态代码块");
        }
        public Person(){
            System.out.println("构造方法");
        }
        public static void main(String[] args) {
            System.out.println(random());        
        }
    }
    //输出结果
    静态代码块
    0.9107008895679277
    

抽象类

  • 抽象类不能使用new关键字来创建对象,只能通过子类继承来实现。

  • 抽象方法只有方法的声明,没有方法的实现。

  • abstract修饰符可以用来修饰方法也可以用来修饰类,若修饰方法,则该方法是抽象方法;若修饰类,则该类是抽象类。

    public abstract class Action{
    		public abstract void doSomething();
    }
    public class A extends Action{
      	@Override
      	public void doSomething(){
          //方法实现
        }
    }
    

注:抽象类中也是可以有构造函数的。虽然抽象类不能实例化,但是抽象类被继承之后,它的派生类可以实例化;而派生类在实例化调用构造函数的时候会先调用基类中的构造函数,所以抽象类的构造函数也是可以被调用的,所以抽象类中可以有构造函数。

接口

JavaOOD思想 功能
普通类 只有具体的实现
抽象类 具体实现和规范(抽象方法)
接口 只有规范
  • 接口是一种规范,定义了一组规则,体现了现实世界中“如果你是...则必须能...”的思想。

  • 接口本质是一种契约,相当于一种Java的法律规范。

  • 声明类的关键字是class,声明接口的关键字是interface

  • 接口中所有的方法均默认public abstract,所有常量默认public static final

  • 实现接口方法通过子类implements关键词实现,同时子类可以实现多个接口。

    //定义接口
    public interface userService {
        void add(String name);
        void delete(String name);
        void update(String name);
        void query(String name);
    }
    //接口实现
    import .../.userService;
    public class Main implements userService {
        @Override
        public void add(String name) {
    
        }
    
        @Override
        public void delete(String name) {
    
        }
    
        @Override
        public void update(String name) {
    
        }
    
        @Override
        public void query(String name) {
    
        }
    }
    

内部类

//定义内部类
public class Outer{
    private static int id = 10 ;
    public void out(){
        System.out.println("this is Outer");
    }
    public static class Inner{
        public void in(){
            System.out.println("this is Inner");
        }
        //通过内部类获取外部私有信息
        public void getID(){
            System.out.println(id);
        }
    }
}
//调用内部类
public class Main {
    public static void main(String[] args) {
        Outer.Inner inner = new Outer.Inner();
        inner.getID();
    }
}
//输出结果
10

第三章:Java常用类

  1. Math--BigDecimal

    public static void main(String[] args) {
            BigDecimal b1 = new BigDecimal("1234");
            BigDecimal b2 = new BigDecimal("1234");
            BigDecimal b3 = b1.divide(b2,3,BigDecimal.ROUND_HALF_DOWN);
            System.out.println(b3);
        }
    
  2. String

    public class StringTest {
    
    	public static void main(String[] args) {
    		String a = "123;456;789;123 ";
    		System.out.println(a.charAt(0)); // 返回第0个元素
    		System.out.println(a.indexOf(";")); // 返回第一个;的位置
    		System.out.println(a.concat(";000")); // 连接一个新字符串并返回,a不变
    		System.out.println(a.contains("000")); // 判断a是否包含000
    		System.out.println(a.endsWith("000")); // 判断a是否以000结尾
    		System.out.println(a.equals("000")); // 判断是否等于000
    		System.out.println(a.equalsIgnoreCase("000"));// 判断在忽略大小写情况下是否等于000
    		System.out.println(a.length()); // 返回a长度
    		System.out.println(a.trim()); // 返回a去除前后空格后的字符串,a不变
    		String[] b = a.split(";"); // 将a字符串按照;分割成数组
    		for (int i = 0; i < b.length; i++) {
    			System.out.println(b[i]);
    		}
    
    		System.out.println("===================");
    
    		System.out.println(a.substring(2, 5)); // 截取a的第2个到第5个字符 a不变
    		System.out.println(a.replace("1", "a"));
    		System.out.println(a.replaceAll("1", "a")); // replaceAll第一个参数是正则表达式
    
    		System.out.println("===================");
    
    		String s1 = "12345?6789";
    		String s2 = s1.replace("?", "a");
    		String s3 = s1.replaceAll("[?]", "a");
    		// 这里的[?] 才表示字符问号,这样才能正常替换。不然在正则中会有特殊的意义就会报异常
    		System.out.println(s2);
    		System.out.println(s3);
    		System.out.println(s1.replaceAll("[\\d]", "a")); //将s1内所有数字替换为a并输出,s1的值未改变。
    	}
    }
    
  3. Time

  4. Format

第四章:Java异常处理

  • Java异常包含Throwable、Error和Exception三类,其中Throwable是所有错误的祖先,Error是系统内部错误,Exception是程序有关的异常。

  • Java采取try-catch-finally框架处理异常结构,其中try负责正常的业务逻辑代码,catch负责捕捉try抛出的异常类型,finally则在try-catch最后执行。try必须存在,catch和finally至少有一个,且三个模块均可在内部嵌套try-catch-finally框架

  • catch块可类比case,可以有多个,进入入口取决于try抛出的异常,当抛出异常同某个catch块中的形参类型一致,则执行该catch块代码。进入catch块后,并不会返回到try发生的位置,也不会执行后续的catch块,一个异常只能进入一个catch块。

  • throws异常处理中,若该方法被覆盖,覆盖它的方法必须抛出相同的异常,或者异常的子类。即父类方法抛出的异常,子类方法必须同样抛出那些异常或者异常的真子集,也就是不能抛出新的异常。

    public class TryDemo {
    	public static void main(String[] args) {
    		try
    		{
    			int a = 5/2; //无异常
    			System.out.println("a is " + a);
    		}
    		catch(Exception ex)
    		{
    			ex.printStackTrace();
    		}
    		finally
    		{
    			System.out.println("Phrase 1 is over");
    		}
    		try
    		{
    			int a = 5/0; //ArithmeticException
    			System.out.println("a is " + a);
    		}
    		catch(Exception ex)
    		{
    			ex.printStackTrace();
    		}
    		finally
    		{
    			System.out.println("Phrase 2 is over");
    		}
    		try
    		{
    			int a = 5/0; //ArithmeticException
    			System.out.println("a is " + a);
    		}
    		catch(Exception ex)
    		{
    			ex.printStackTrace();
    			int a = 5/0; //ArithmeticException
    		}
    		finally
    		{
    			System.out.println("Phrase 3 is over");
    		}
    	}
    }
    

第五章:Java文件读写

Java - IO

import java.io.*;
public class FileAttributeTest{
  public static void main(String[] args){
	//创建目录
	File d=new File("c:/temp");
	if(!d.exists())
	{
		d.mkdirs();  //mkdir 创建单级目录  mkdirs 连续创建多级目录
	}
	System.out.println("Is d directory? " + d.isDirectory());
	
	//创建文件  
    File f=new File("C:/temp/abc.txt");    
    if(!f.exists())
    {    	
      try
      {
        f.createNewFile(); //创建abc.txt
      }
      catch(IOException e){ //可能会因为权限不足或磁盘已满报错
    	  e.printStackTrace();
      }
    }  
    
    //输出文件相关属性
    System.out.println("Is f file? " + f.isFile());
    System.out.println("Name: "+f.getName());
    System.out.println("Parent: "+f.getParent());
    System.out.println("Path: "+f.getPath());
    System.out.println("Size: "+f.length()+" bytes");
    System.out.println("Last modified time: "+f.lastModified()+"ms");
    
    //遍历d目录下所有的文件信息
    System.out.println("list files in d directory");
    File[] fs = d.listFiles();  //列出d目录下所有的子文件,不包括子目录下的文件
    for(File f1:fs)
    {
    	System.out.println(f1.getPath());
    }
    
    //f.delete(); //删除此文件
    //d.delete(); //删除目录
  }
}

Java - NIO

import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Date;

public class FilesTest {
	
	public static void main(String[] a)
	{
		moveFile();
		fileAttributes();
		createDirectory();
	}

	public static void moveFile() {
		Path from = Paths.get("c:/temp", "abc.txt");
		//移动c:/temp/abc.txt到c:/temp/test/def.txt,如目标文件已存在,就替换
		Path to = from.getParent().resolve("test/def.txt");
		try {
			//文件的大小bytes
			System.out.println(Files.size(from));
			//调用文件移动方法  如果目标文件已经存在,就替换
			Files.move(from, to, StandardCopyOption.REPLACE_EXISTING);
		} catch (IOException e) {
			System.err.println("移动文件错误" + e.getMessage());
		}
	}
		
	public static void fileAttributes(){
		Path path = Paths.get("c:/temp");
		//1
		System.out.println(Files.isDirectory(path, LinkOption.NOFOLLOW_LINKS));
		//2
		try {
			//获得文件的基础属性
			BasicFileAttributes attributes = Files.readAttributes(path, BasicFileAttributes.class);
			System.out.println(attributes.isDirectory());
			System.out.println(new Date(attributes.lastModifiedTime().toMillis()).toLocaleString());
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public static void createDirectory(){
		Path path = Paths.get("c:/temp/test");
		try {
			//创建文件夹
			if(Files.notExists(path)){
				Files.createDirectories(path);
				System.out.println("create dir");
			}else{
				System.out.println("dir exists");
			}
			Path path2 = path.resolve("A.java"); 
			Path path3 = path.resolve("B.java");
			Path path4 = path.resolve("C.txt");
			Path path5 = path.resolve("D.jpg");
			Files.createFile(path2);
			Files.createFile(path3);
			Files.createFile(path4);
			Files.createFile(path5);
			
			//不加条件遍历
			DirectoryStream<Path> paths = Files.newDirectoryStream(path);
			for(Path p : paths){
				System.out.println(p.getFileName());
			}
			System.out.println();
			
			//创建一个带有过滤器,过滤文件名以java txt结尾的文件
			DirectoryStream<Path> pathsFilter = Files.newDirectoryStream(path, "*.{java,txt}");
			for(Path p : pathsFilter){
				System.out.println(p.getFileName());
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

第六章:Java常用数据结构

列表 List

  • List是有序的Collection,允许重复元素。

  • List主要实现:ArrayList(非同步)、LinkedList(非同步)、Vector(同步)

    1. ArrayList

      • 以数组实现的列表,不支持同步

        List list = Collections.synchronizedList(new ArrayList(...));

      • 利用索引位置可以快速定位访问

      • 不适合指定位置的插入、删除操作

      • 适合变动不大,主要用于查询的数据

      • 和Java数组相比,其容量是可动态调整的

      • ArrayList在元素填满容器时会自动扩充容器大小的50%

      import java.util.ArrayList;
      import java.util.Iterator;
      //Vector 几乎和ArrayList一样,除了Vector本身是同步的
      
      public class ArrayListTest {
      	public static void main(String[] a) {  
      	    ArrayList<Integer> al = new ArrayList<Integer>();  
      	    al.add(3);  
      	    al.add(2);          
      	    al.add(1);  
      	    al.add(4);  
      	    al.add(5);  
      	    al.add(6);  
      	    al.add(new Integer(6));  
      	  
      	    System.out.print("The third element is  ");
      	    System.out.println(al.get(3));
      	    al.remove(3);  //删除第四个元素,后面元素往前挪动
      	    al.add(3, 9);  //将9插入到第4个元素,后面元素往后挪动
      	    
      	    System.out.println("======遍历方法=============");
      	    
      	    ArrayList<Integer> as = new ArrayList<Integer>(100000);
      	    for (int i=0; i<100000; i++)
      	    {
      	    	as.add(i);
      	    }
          	//三种遍历方式性能比较
          	//for-each > 随机索引值遍历 > 迭代器遍历
      	    traverseByIterator(as);
      	    traverseByIndex(as);
      	    traverseByFor(as);    
      	}  
      	public static void traverseByIterator(ArrayList<Integer> al)
      	{
      		long startTime = System.nanoTime();
      		System.out.println("============迭代器遍历=============="); 
      	    Iterator<Integer> iter1 = al.iterator();  
      	    while(iter1.hasNext()){  
      	        iter1.next();  
      	    }
      		long endTime = System.nanoTime();
      	    long duration = endTime - startTime;
      	    System.out.println(duration + "纳秒");
      	}
      	public static void traverseByIndex(ArrayList<Integer> al)
      	{
      		long startTime = System.nanoTime();
      		System.out.println("============随机索引值遍历=============="); 
      	    for(int i=0;i<al.size();i++)
      	    {
      	    	al.get(i);
      	    }
      		long endTime = System.nanoTime();
      	    long duration = endTime - startTime;
      	    System.out.println(duration + "纳秒");
      	}
      	public static void traverseByFor(ArrayList<Integer> al)
      	{
      		long startTime = System.nanoTime();
      		System.out.println("============for循环遍历=============="); 
      	    for(Integer item : al)
      	    {
      	    	;
      	    }
      		long endTime = System.nanoTime();
      	    long duration = endTime - startTime;
      	    System.out.println(duration + "纳秒");
      	}
      }
      
    2. LinkedList

      • 以双向链表实现的列表,不支持同步

        List list = Collections.synchronizedList(new LinkedList(...));

      • 可被当作堆栈、队列和双端队列进行操作

      • 顺序访问高效,随机访问较差,中间插入和删除高效

      • 适用于经常变化的数据

      import java.util.ArrayList;
      import java.util.Iterator;
      import java.util.LinkedList;
      
      public class LinkedListTest {
      
      	public static void main(String[] args) {
      		LinkedList<Integer> ll = new LinkedList<Integer>();  
      	    ll.add(3);  
      	    ll.add(2);  
      	    ll.add(5);  
      	    ll.add(6);  
      	    ll.add(6);  
      	    System.out.println(ll.size());
      	    ll.addFirst(9);  //在头部增加9
      	    ll.add(3, 10);   //将10插入到第四个元素,四以及后续的元素往后挪动
      	    ll.remove(3);    //将第四个元素删除
      	    
      	    LinkedList<Integer> list = new LinkedList<Integer>();
      	    for (int i=0; i<100000; i++)
      	    {
      	    	list.add(i);
      	    }
          	//三种遍历方式性能比较
          	//for-each > 迭代器遍历 > 随机索引值遍历
      	    traverseByIterator(list);
      	    traverseByIndex(list);
      	    traverseByFor(list);    
      
      	}
      	
      	public static void traverseByIterator(LinkedList<Integer> list)
      	{
      		long startTime = System.nanoTime();
      		System.out.println("============迭代器遍历=============="); 
      	    Iterator<Integer> iter1 = list.iterator();  
      	    while(iter1.hasNext()){  
      	        iter1.next();  
      	    }
      		long endTime = System.nanoTime();
      	    long duration = endTime - startTime;
      	    System.out.println(duration + "纳秒");
      	}
      	public static void traverseByIndex(LinkedList<Integer> list)
      	{
      		long startTime = System.nanoTime();
      		System.out.println("============随机索引值遍历=============="); 
      	    for(int i=0;i<list.size();i++)
      	    {
      	    	list.get(i);
      	    }
      		long endTime = System.nanoTime();
      	    long duration = endTime - startTime;
      	    System.out.println(duration + "纳秒");
      	}
      	public static void traverseByFor(LinkedList<Integer> list)
      	{
      		long startTime = System.nanoTime();
      		System.out.println("============for循环遍历=============="); 
      	    for(Integer item : list)
      	    {
      	    	;
      	    }
      		long endTime = System.nanoTime();
      	    long duration = endTime - startTime;
      	    System.out.println(duration + "纳秒");
      	}
      }
      
      

      ArrayList适用于较多的查询情况,LinkedList适用于较多的增删情况。

    3. Vector

      • 和ArrayList类似,可变数组实现的列表

      • Vector同步,适合在多线程下使用

      • 原先不属于JCF框架,属于Java最早的数据结构,性能较差

      • 从JDK1.2开始,Vector被重写,并纳入到JCF

      • 官方文档建议在非同步情况下,优先采用ArrayList

      import java.util.ArrayList;
      import java.util.Enumeration;
      import java.util.Iterator;
      import java.util.Vector;
      
      public class VectorTest {
      
      	public static void main(String[] args) {
      		Vector<Integer> v = new Vector<Integer>();
      		v.add(1);
      		v.add(2);
      		v.add(3);
      		v.remove(2);
      		v.add(1, 5);
      		System.out.println(v.size());
      
      		System.out.println("======遍历方法=============");
      
      		Vector<Integer> v2 = new Vector<Integer>(100000);
      		for (int i = 0; i < 100000; i++) {
      			v2.add(i);
      		}
          //四种遍历方式性能比较
          //for-each ≈ Enumeration遍历 > 迭代器遍历 > 随机索引值遍历
      		traverseByIterator(v2);
      		traverseByIndex(v2);
      		traverseByFor(v2);
      		traverseByEnumeration(v2);
      	}
      
      	public static void traverseByIterator(Vector<Integer> v) {
      		long startTime = System.nanoTime();
      		System.out.println("============迭代器遍历==============");
      		Iterator<Integer> iter1 = v.iterator();
      		while (iter1.hasNext()) {
      			iter1.next();
      		}
      		long endTime = System.nanoTime();
      		long duration = endTime - startTime;
      		System.out.println(duration + "纳秒");
      	}
      
      	public static void traverseByIndex(Vector<Integer> v) {
      		long startTime = System.nanoTime();
      		System.out.println("============随机索引值遍历==============");
      		for (int i = 0; i < v.size(); i++) {
      			v.get(i);
      		}
      		long endTime = System.nanoTime();
      		long duration = endTime - startTime;
      		System.out.println(duration + "纳秒");
      	}
      
      	public static void traverseByFor(Vector<Integer> v) {
      		long startTime = System.nanoTime();
      		System.out.println("============for循环遍历==============");
      		for (Integer item : v) {
      			;
      		}
      		long endTime = System.nanoTime();
      		long duration = endTime - startTime;
      		System.out.println(duration + "纳秒");
      	}
      
      	public static void traverseByEnumeration(Vector<Integer> v) {
      		long startTime = System.nanoTime();
      		System.out.println("============Enumeration遍历==============");
      		for (Enumeration<Integer> enu = v.elements(); enu.hasMoreElements();) {
      			enu.nextElement();
      		}
      		long endTime = System.nanoTime();
      		long duration = endTime - startTime;
      		System.out.println(duration + "纳秒");
      	}
      }
      

集合 Set

  • 集合性质

    • 确定性:对任意对象都能判定其是否属于某一个集合

    • 互异性:集合内每个元素都是无差异的,注意是内容差异

    • 无序性:集合内的顺序无关

  • List主要实现:HashSet (基于散列函数的集合,无序,不支持同步)、TreeSet (基于树结构的集合,可排序的,不支持同步)、LinkedHashSet(基于散列函数和双向链表的集合,可排序的,不支持同步)。

    1. HashSet

      • 基于HashMap实现的,可以容纳null元素, 不支持同步

        Set s = Collections.synchronizedSet(new HashSet(...));

      • add 添加一个元素

      • clear 清除整个HashSet

      • contains 判定是否包含一个元素

      • remove 删除一个元素 size 大小

      • retainAll 计算两个集合交集

      import java.util.ArrayList;
      import java.util.HashSet;
      import java.util.Iterator;
      
      public class HashSetTest {
      	public static void main(String[] args) {
      		HashSet<Integer> hs = new HashSet<Integer>();
      		hs.add(null);
      		hs.add(1000);
      		hs.add(20);
      		hs.add(3);
      		hs.add(40000);
      		hs.add(5000000);
      		hs.add(3);                      //3 重复
      		hs.add(null);                   //null重复
      		System.out.println(hs.size());  //6
      		if(!hs.contains(6))
      		{
      			hs.add(6);
      		}
      		System.out.println(hs.size());  //7
      		hs.remove(4);
      		System.out.println(hs.size());  //6
      		//hs.clear();
      		//System.out.println(hs.size());  //0
      		
      		System.out.println("============for循环遍历=============="); 
      	    for(Integer item : hs)
      	    {
      	    	System.out.println(item);
      	    }
      	    
      	    System.out.println("============测试集合交集==============");
      	    
      	    HashSet<String> set1 = new HashSet<String>();
      	    HashSet<String> set2 = new HashSet<String>();
      
              set1.add("a");
              set1.add("b");
              set1.add("c");
      
              set2.add("c");
              set2.add("d");
              set2.add("e");
      
              //交集
              set1.retainAll(set2);
              System.out.println("交集是 "+set1);
              
              System.out.println("============测试多种遍历方法速度==============");
      		
      		HashSet<Integer> hs2 = new HashSet<Integer>();
      		for(int i=0;i<100000;i++)	{
      			hs2.add(i);
      		}
      		traverseByIterator(hs2);
      		traverseByFor(hs2);		
      	}
      	
      	public static void traverseByIterator(HashSet<Integer> hs)
      	{
      		long startTime = System.nanoTime();
      		System.out.println("============迭代器遍历=============="); 
      	    Iterator<Integer> iter1 = hs.iterator();  
      	    while(iter1.hasNext()){  
      	        iter1.next();  
      	    }
      		long endTime = System.nanoTime();
      	    long duration = endTime - startTime;
      	    System.out.println(duration + "纳秒");
      	}
      	public static void traverseByFor(HashSet<Integer> hs)
      	{
      		long startTime = System.nanoTime();
      		System.out.println("============for循环遍历=============="); 
      	    for(Integer item : hs)
      	    {
      	    	;
      	    }
      		long endTime = System.nanoTime();
      	    long duration = endTime - startTime;
      	    System.out.println(duration + "纳秒");
      	}
      }
      
    2. LinkedHashSetTest

      • 继承HashSet,也是基于HashMap实现的,可以容纳null元素

      • 不支持同步

        Set s = Collections.synchronizedSet(new LinkedHashSet(...));

      • 方法和HashSet基本一致

        add, clear, contains, remove, size

      • 通过一个双向链表维护插入顺序

      import java.util.ArrayList;
      import java.util.HashSet;
      import java.util.Iterator;
      import java.util.LinkedHashSet;
      
      public class LinkedHashSetTest {
      	public static void main(String[] args) {
      		LinkedHashSet<Integer> lhs = new LinkedHashSet<Integer>();
      		lhs.add(null);
      		lhs.add(1000);
      		lhs.add(20);
      		lhs.add(3);
      		lhs.add(40000);
      		lhs.add(5000000);
      		lhs.add(3);                      //3 重复
      		lhs.add(null);                   //null 重复
      		System.out.println(lhs.size());  //6
      		if(!lhs.contains(6))
      		{
      			lhs.add(6);
      		}
      		System.out.println(lhs.size());  //7
      		lhs.remove(4);
      		System.out.println(lhs.size());  //6
      		//lhs.clear();
      		//System.out.println(lhs.size());  //0
      		
      		System.out.println("============for循环遍历=============="); 
      	    for(Integer item : lhs)
      	    {
      	    	System.out.println(item);
      	    }
      		
      		LinkedHashSet<Integer> lhs2 = new LinkedHashSet<Integer>();
      		for(int i=0;i<100000;i++)
      		{
      			lhs2.add(i);
      		}
      		traverseByIterator(lhs2);
      		traverseByFor(lhs2);
      		
      	}
      	
      	public static void traverseByIterator(LinkedHashSet<Integer> hs)
      	{
      		long startTime = System.nanoTime();
      		System.out.println("============迭代器遍历=============="); 
      	    Iterator<Integer> iter1 = hs.iterator();  
      	    while(iter1.hasNext()){  
      	        iter1.next();  
      	    }
      		long endTime = System.nanoTime();
      	    long duration = endTime - startTime;
      	    System.out.println(duration + "纳秒");
      	}
      	public static void traverseByFor(LinkedHashSet<Integer> hs)
      	{
      		long startTime = System.nanoTime();
      		System.out.println("============for循环遍历=============="); 
      	    for(Integer item : hs)
      	    {
      	    	;
      	    }
      		long endTime = System.nanoTime();
      	    long duration = endTime - startTime;
      	    System.out.println(duration + "纳秒");
      	}
      }
      
    3. TreeSet

      • 基于TreeMap实现的,不可以容纳null元素,不支持同步

        SortedSet s = Collections.synchronizedSortedSet(new TreeSet(...));

      • add 添加一个元素

      • clear 清除整个TreeSet

      • contains 判定是否包含一个元素

      • remove 删除一个元素 size 大小

      • 根据compareTo方法或指定Comparator排序

      import java.util.ArrayList;
      import java.util.HashSet;
      import java.util.Iterator;
      import java.util.LinkedHashSet;
      import java.util.TreeSet;
      
      public class TreeSetTest {
      	public static void main(String[] args) {
      		TreeSet<Integer> ts = new TreeSet<Integer>();
      		// ts.add(null);  错误,不支持null
      		ts.add(1000);
      		ts.add(20);
      		ts.add(3);
      		ts.add(40000);
      		ts.add(5000000);
      		ts.add(3);                      //3 重复
      		System.out.println(ts.size());  //5
      		if(!ts.contains(6))
      		{
      			ts.add(6);
      		}
      		System.out.println(ts.size());  //6
      		ts.remove(4);
      		System.out.println(ts.size());  //5
      		//lhs.clear();
      		//System.out.println(lhs.size());  //0
      		
      		System.out.println("============for循环遍历=============="); 
      	    for(Integer item : ts)
      	    {
      	    	System.out.println(item);
      	    }
      	    
      		TreeSet<Integer> ts2 = new TreeSet<Integer>();
      		for(int i=0;i<100000;i++)
      		{
      			ts2.add(i);
      		}
      		traverseByIterator(ts2);
      		traverseByFor(ts2);
      		
      	}
      	
      	public static void traverseByIterator(TreeSet<Integer> hs)
      	{
      		long startTime = System.nanoTime();
      		System.out.println("============迭代器遍历=============="); 
      	    Iterator<Integer> iter1 = hs.iterator();  
      	    while(iter1.hasNext()){  
      	        iter1.next();  
      	    }
      		long endTime = System.nanoTime();
      	    long duration = endTime - startTime;
      	    System.out.println(duration + "纳秒");
      	}
      	public static void traverseByFor(TreeSet<Integer> hs)
      	{
      		long startTime = System.nanoTime();
      		System.out.println("============for循环遍历=============="); 
      	    for(Integer item : hs)
      	    {
      	    	;
      	    }
      		long endTime = System.nanoTime();
      	    long duration = endTime - startTime;
      	    System.out.println(duration + "纳秒");
      	}
      }
      
    4. 上述三种方法比较

      HashSet是无序输出的, LinkedHashSet是按照插入的顺序进行遍历输出, TreeSet是按照所存储的对象大小升序输出

      HashSet, LinkedHashSet, TreeSet的元素都只能是对象

      HashSet和LinkedHashSet判定元素重复的原则

      ​ –判定两个元素的hashCode返回值是否相同,若不同,返回false

      ​ –若两者hashCode相同,判定equals方法,若不同,返回false;否则

      返回true。

      ​ –hashCode和equals方法是所有类都有的,因为Object类有

      TreeSet判定元素重复的原则

      ​ –需要元素继承自Comparable接口

      ​ –比较两个元素的compareTo方法

JCF中的工具类

  • 不存储数据,而是在数据容器上,实现高效操作

    • 排序

    • 搜索

  • Arrays类:处理对象是数组

    排序:对数组排序, sort/parallelSort

    查找:从数组中查找一个元素, binarySearch

    批量拷贝:从源数组批量复制元素到目标数组, copyO。

    批量赋值:对数组进行批量赋值, fill

    等价性比较:判定两个数组内容是否相同, equals

    import java.util.Arrays;
    import java.util.Random;
    
    public class ArraysTest { 
    	public static void main(String[] args) {
    		testSort();
    		testSearch();
    		testCopy();
    		testFill();
    		testEquality();
    	}
    	public static void testSort() {
    		Random r = new Random();
    		int[] a = new int[10];
    		for(int i=0;i<a.length;i++)	{
    			a[i] = r.nextInt();
    		}
    		System.out.println("===============测试排序================");
    		System.out.println("排序前");
    		for(int i=0;i<a.length;i++)	{
    			System.out.print(a[i] + ",");
    		}
    		System.out.println();
    		System.out.println("排序后");
    		Arrays.sort(a);
    		for(int i=0;i<a.length;i++)	{
    			System.out.print(a[i] + ",");
    		}
    		System.out.println();		
    	}
    
    	public static void testSearch() {
    		Random r = new Random();
    		int[] a = new int[10];
    		for(int i=0;i<a.length;i++)
    		{
    			a[i] = r.nextInt();
    		}
    		a[a.length-1] = 10000;
    		System.out.println("===========测试查找============");
    		System.out.println("10000 的位置是" + Arrays.binarySearch(a, 10000));
    	}
    	
    	public static void testCopy() {
    		Random r = new Random();
    		int[] a = new int[10];
    		for(int i=0;i<a.length;i++)
    		{
    			a[i] = r.nextInt();
    		}
    		int[] b = Arrays.copyOf(a, 5);
    		System.out.println("===========测试拷贝前五个元素============");
    		System.out.print("源数组:");
    		for(int i=0;i<a.length;i++)
    		{
    			System.out.print(a[i] + ",");
    		}
    		System.out.println();
    		System.out.print("目标数组:");
    		for(int i=0;i<b.length;i++)
    		{
    			System.out.print(b[i] + ",");
    		}
    		System.out.println();
    	}
    	public static void testFill() {
    		int[] a = new int[10];
    		Arrays.fill(a, 100);
    		Arrays.fill(a, 2, 8, 200);
    		System.out.println("===========测试批量赋值============");
    		System.out.print("数组赋值后:");
    		for(int i=0;i<a.length;i++)
    		{
    			System.out.print(a[i] + ",");
    		}
    		System.out.println();
    	}
    	public static void testEquality() {
    		int[] a = new int[10];
    		Arrays.fill(a, 100);
    		int[] b = new int[10];
    		Arrays.fill(b, 100);		
    		System.out.println(Arrays.equals(a, b));
    		b[9] = 200;
    		System.out.println(Arrays.equals(a, b));
    	}
    }
    
  • Collections类:处理对象是Collection以及其子类

    排序:对List进行排序,sort。

    搜索:从List中搜索元素,binarySearch

    批量赋值:对List批量赋值,fill。

    最大、最小:查找集合中最大/小值,max,min

    反序:将List 反序排列,reverse

    import java.util.ArrayList;
    import java.util.Collections;
    
    public class CollectionsTest {
    
    	public static void main(String[] args) {
    		ArrayList<Integer> list = new ArrayList<Integer>();
            list.add(1);
            list.add(12);
            list.add(2);
            list.add(19);
             
            // 排序
            Collections.sort(list);
            // 检索
            System.out.println("元素所在的索引值是:" + Collections.binarySearch(list, 12));
            //最大最小
            System.out.println("最大值:" + Collections.max(list));
            System.out.println("最小值:" + Collections.min(list));
            Collections.reverse(list); //翻转不需要用到排序
             
            Collections.fill(list, 100); //全部赋值为100
    	}
    }
    
    
  • 对象比较

    对象实现Comparable接口(需要修改对象类)

    ​ –compareTo方法

    ​ • > 返回1, ==返回0,<返回-1

    ​ –Arrays和Collections在进行对象sort时,自动调用该方法

    新建Comparator(适用于对象类不可更改的情况)

    ​ –compare方法

    ​ • > 返回1, ==返回0,<返回-1

    ​ –Comparator比较器将作为参数提交给工具类的sort方法

猜你喜欢

转载自www.cnblogs.com/paragon/p/13396332.html