自认为简洁明了的Java基础学习笔记

本文就 Java 基本的语法和要点做笔记式记录解析
旨在更好的将我学习 Java 的经验分享给大家!

因为本人懒,笔记并没有面面俱到,本文不断更新完善中

废话不多说现在开始:

Java面向对象OOP01

Java面向对象三大特征:封装 继承 多态

对象的创建和使用

创建

通过new关键字

类名 对象名 = new 类名(); 注意这里new后面的 类名() 是该类的构造方法,该知识点后面详解

例如:

Person p = new Person()

使用

对象名.属性名; 获取其某个属性

对象名.方法名(); 使用其功能

例如:

// 获取其属性
p.neme;
p.age;

// 也可以设置其属性
p.neme = "张三";
p.age = "18";
p.sex = "男"

// 使用方法
p.eat();
p.walk();

代码示例:

public class Person{
    // 属性
    String name;
    String sex;
    int age;
    
    // 行为(方法)
    public void eat(){
        System.out.println("我"+name+"饿了!要吃饭!");
    }
    public void doSome(){
        System.out.println("我"+name+"想做某些事!");
    }
    public void walk(){
    	System.out.println("我"+name+"要去压马路!");
    }
    public void sleep(){
    	System.out.println("我"+name+"困了!要睡觉!");
    }
    
    
    
    public static void main(String[] args){
    
    // 实例化对象
    Person p = new Person();
    
    // 设置其属性
    p.name = "张三";
    p.age = 18;
    p.sex = "男";
    
    // 使用方法
    p.eat();
	p.walk();
    
     System.out.println(p.age);
    
    }
    
}

以上代码在控制台输出的结果为:

我张三饿了!要吃饭!

我张三要去压马路!

18

方法语法

属性

方法在Java中不能独立存在,其必须属于某个类和对象

一般用static修饰的方法,属于类,不属于这个类的实例对象

使用起来就不需要实例化其对象,直接类名.方法名

This.的三个用法

第一种情况

构造函数中对象成员变量的初始化时使用,用来区分成员变量跟形式参数

public class StudyThis {
	private String name;
	private int age;
	public StudyThis(String name,int age){
		this.name=name;
		this.age=age;
	}
}

第二种情况

假设有两个类,容器类Container和内容类Component,在Container的成员方法中需要调用Component类的一个对象。Component的构造函数中需要一个调用它的Container类作为参数

class Container{
	Component comp;
	public void addComponent(){
		comp=new Component(this);
	}
}
class Component{
    Container myContainer;
    public Component(Container c){
        myContainer=c;
    }
}

第三种情况

构造方法不能想其他方法一样被调用,只能在系统初始化一个对象时被系统调用。虽然构造方法不能被其他函数调用,但是可以被该类的其他构造方法调用,这时用this即可

class Person{
	int age;
	String name;
	public Person(){
	}
	public Person(int age){
		this.age=age;
	}
	public Person(int age,String name){
		this(age);
		this.name=name;
	}
}

Java面向对象OOP02

访问修饰符

访问的范围 大—>小: public protected 不写访问修饰符 private

  • public 公共访问的 在任何地方都可以有可以访问的基础
  • protected
  • 不写 默认权限 也叫**包访问权限,**在同一个包中 可以访问

static方法

用static修饰的方法叫 静态方法 可以直接调用 无需创建对象

封装

封装类 也称之为 javabean / 实体类 / entity / pojo

  • 封装是一种做法 可以控制类类可访问属性或方法的 访问权限 的做法
  • 在进行了封装之后 如要设置变量的值时 要通过 指定的方法 来设置,在此设置方法内可以添加一些逻辑判断
  • 通过:分包 和 访问权限修饰符 来做控制。以及常见的封装做法

示例代码

public class Cat {
	private String name;
	private int age;
	private String sex;
	
	// 将属性进行封装
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
}

封装后属性的调用

  • 设置属性 对象名.set属性名();
  • 得到属性 对象名.get属性名();
public class TestCat {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Cat tom = new Cat();
		tom.setName("Tom");
		tom.setAge(8);
		tom.setSex("公");
		
		System.out.println("我是一只猫,我的名字是:"+tom.getName()+"我的年龄是:"+tom.getAge()+"我的性别是:"+tom.getSex()+"!");
	}
}

在设置属性方法里添加逻辑判断

public void setAge(int age) {
		if(age<0 || age>50) { //在设置属性方法里添加逻辑判断
			System.out.println("您输入的年龄不正常!");
			return; //如果输入的年龄不正常则返回默认值
		}
		this.age = age;
}

系统常用类

类 Math

java中关于数字的运算(都为静态方法可以直接调用)

1、Math.PI

是一个字段 表示圆周率

示例代码

System.out.println(Math.PI);

2、abs(数据类型 a) 返回一个绝对值

3、cbrt(double a) /sqrt(double a) 返回double类型的立方根/平方根

4、max/min 传入两个变量 返回两个变量中较大/较小的一个

5、pow(double a, double b) 返回第一个参数的第二个参数次幂的值

6、随机数生成器 random() 返回带正号的 double 值,该值大于等于 0.0 且小于 1.0

7、ceil(double a)/floor(double a) 返回距离参数最近的整数 ceil为大于等于这个参数,例如5.3取6;floor为小于等于这个参数,例如5.3取5

类 Random

需要创建对象

创建一个随机数生成器:

Random r = new Random();

方法

  • nextInt(int n) 返回一个伪随机数,它是取自此随机数生成器序列的、在 0(包括)和指定值(不包括)之间均匀分布的 int 值
int num = r.nextInt(100); //生成一个0-99之间的随机数 可将此嵌套在循环里
  • next数据类型();

类 BigDecimal

在Math包下 需要导包,用于计算无限精度的数据 常用于货币的计算

1、创建一个BigDecimal类型的“数”

BigDecimal a1 = new BigDecimal("549846513");
BigDecimal a2 = new BigDecimal("2654564654351664");

2、做运算

做运算需要调用方法,即 .计算方法的英文单词()

示例代码

BigDecimal result = a1.multiply(a2);
System.out.println(result);

3、指定精度

示例代码

a3.divide(a4,20/*小数点后20位*/,RoundingMode.HALF_UP/*四舍五入*/)

也可以直接写在syso

System.out.println(a3.divide(a4,20/*小数点后20位*/,RoundingMode.HALF_UP/*四舍五入*/));

或者

double money = 456.168511;
DecimalFormat bd = new DecimalFormat("0.0"); //创建一个DecimalFormat对象 并且 规定格式,保留一位小数
System.out.println(bd.format(money));

输出结果为:456.2

类 BigInteger

与BigDecimal类似 但BigInteger传的是整数

类 UUID

表示通用唯一标识符 (UUID) 的类。 UUID 表示一个 128 位的值

生成一个诸如0xFFFFFFFF00000000的字符串,例如我们平时下载的某些文件的文件名

  • randomUUID() 静态方法 生成UUID
  • toString() 将一个 引用类型 转换成 字符串类型

代码示例

//得到一个随机的uuid对象
UUID uuid = UUID.randomUUID();
//得到uuid对象的16进制字符串表示形式
String uuidStr = uuid.toString();
System.out.println(uuidStr);

输出结果为:7831ce66-e19f-4937-8eb3-1625cfa89100

类 String

创建了一个字符串 即为创建了一个String对象

  • String.valueOf 方法 将其他类型的变量转为String类型
String str01 = String.valueOf(num01); //num01为int型
  • length() 返回此字符串的长度
String str = "我爱钢铁侠!";
System.out.println(str.length());

执行结果为 6

  • charAt(int index) 传入字符串的字符下标,返回指定索引处的 char 值,即字符的ASCII码值
System.out.println(str.charAt(2));
  • replace(char oldChar, char newChar) 返回一个新的字符串,它是通过用 newChar(新字符) 替换此字符串中出现的所有 oldChar(原有字符) 字符串的替换
String str = "SSDOAOOOd";
str = str.replace("O", "o");
System.out.println(str);

输出结果为:SSDoAoood

  • split(String regex) 根据给定正则表达式的匹配拆分此字符串 字符串的拆分
    • 传入值为字符串(按此字符串为间隔来拆分),返回值为String[]
String str = "今天开始大家要是用Typora来做每堂课的笔记!Typora是一个很好使用的MD工具Typora!";
String regex = "Typora";
String[] str02 = str.split(regex);// 拆分
System.out.println(Arrays.toString(str02));// 通过Arrays.toString()方法来将数组变成字符串

输出结果为:[今天开始大家要是用, 来做每堂课的笔记!, 是一个很好使用的MD工具, !]

  • 将char型数据转为int型数据

    • 用完 .charAt() 方法后数据会变为ASCII码值,如果想让其变回该下标处数据的int数字
    int n01 = str01.charAt(0)-'0'; //减去一个'0'即可
    

类 Character

  • isUpperCase(char ch) 传入一个char型数据(可由String类下的charAt(int index)方法获得),确定此字符是否为大写字符
  • isLowerCase(char ch) 确定指定字符是否为小写字母

以上两个方法的返回值均为Boolean类型

String str02 = "哈哈哈哈哈tiaTSFB的大声道sDASdFAads";
int up = 0;
int low = 0;
for (int i = 0; i < str02.length(); i++) {
    char c = str02.charAt(i);
    if(Character.isUpperCase(c)) {
        up++;
    }else if(Character.isLowerCase(c)) {
        low++;
    }
}
System.out.println("str02中大写字符有:"+up+"个,小写字符有:"+low+"个!");

输出结果为:str02中大写字符有:9个,小写字符有:8个!

  • hashCode() 返回此 Character 的哈希码
  • isLetter(char ch) 确定指定字符是否为字母。
  • isDigit(char ch) 确认指定字符时候为数字
  • hashCode() 返回此 Character 的哈希码

比较大小写个数的第二种方法

用ASCII码比较 在97-122之间为小写,65-90之间为大写

// 比较字符串大小写个数的第二种方法 
// 用ASCII码比较 在97-122之间为小写,65-90之间为大写
int up02 = 0;
int low02 = 0;
for (int i = 0; i < str02.length(); i++) {
    char c = str02.charAt(i);
    if(c>=97 && c<=122) {
        low02++;
    }else if(c>=65 && c<=90) {
        up02++;
    }
}
System.out.println("str02中大写字符有:"+up02+"个,小写字符有:"+low02+"个!");

类 Format

Java 平台为格式化日期、消息和数字分别提供了三个特殊的 Format 的子类:DateFormatMessageFormatNumberFormat

正则表达式

正则是一个表达式,本身也是一个字符串,用来匹配,查找,替换,分割…其他字符的

单个字符正则:[abcd] 一个字符串只能有abcd里的1个字符构成
其他正则格式可以查看API里的Pattern类

代码示例

String str = "a";
String regex01 = "[abcd]"; //[abcd]为正则格式,用于验证一个字符串是不是abcd这几个中的一个

//匹配验证 字符串 符不符合 某个正则格式
//方法1:String类 里的 boolean matches(String regex)
//方法2:Pattern类 里的 Pattern.matches(regex,串);
System.out.println(str.matches(regex01)); //方法1
System.out.println(Pattern.matches(regex01, str)); //方法2

输出结果:方法1 方法2都是打印true,因为a在[abcd]中

其他字符类正则格式

//字符类 
//	[abc] a、b 或 c(简单类) 
//	[^abc] 任何字符,除了 a、b 或 c(否定) 
//	[a-zA-Z] a 到 z 或 A 到 Z,两头的字母包括在内(范围) 
//	[a-d[m-p]] a 到 d 或 m 到 p:[a-dm-p](并集) 
//	[a-z&&[def]] d、e 或 f(交集) 
//	[a-z&&[^bc]] a 到 z,除了 b 和 c:[ad-z](减去) 
//	[a-z&&[^m-p]] a 到 z,而非 m 到 p:[a-lq-z](减去)

预定义字符类

// 预定义字符类(早就定义好的字符类)
//		预定义字符类 
//		. 任何字符(与行结束符可能匹配也可能不匹配) 
//		\d 数字:[0-9] 
//		\D 非数字: [^0-9] 
//		\s 空白字符:[ \t\n\x0B\f\r] 
//		\S 非空白字符:[^\s] 
//		\w 单词字符:[a-zA-Z_0-9] 
//		\W 非单词字符:[^\w] 

String str01 = "a";
String regex02 = "\\w"; // \在java里是转义的意思 所以\w前面还要写一个\
System.out.println(str01.matches(regex02)); //方法1
System.out.println(Pattern.matches(regex02, str01)); //方法2

以上都只能比较单独一个字符,若要比较多个字符 则需以下写法

Greedy 数量词
X? X,一次或一次也没有
X* X,零次或多次
X+ X,一次或多次
X{n} X,恰好 n 次
X{n,} X,至少 n 次
X{n,m} X,至少 n 次,但是不超过 m 次

边界匹配器 (常用的,其他的查阅API)
^ 行的开头
$ 行的结尾

正则表达式的组合书写可以根据你的意思来验证字符串是否符合标准

代码示例

String str = "AAD";
String str2 = "AAD@#$##$@#";
// 正则表达式
String regex = "^[A-Z]{2,4}|\\W+$"; //2到4个大写字母 或 至少一个非单词字符
String regex2 = "^[A-Z]{2,4}\\W+$"; //2到4个大写字母 然后 紧跟至少一个非单词字符(按照顺序)
System.out.println(str.matches(regex)); //输出结果为:true
System.out.println(str.matches(regex2)); //输出结果为:false
System.out.println(str2.matches(regex2)); //输出结果为:true
// 或用Pattern.matches(正则,串);
// 如果想包含某个字符串呢?
// 例如验证在字符串结尾包不包含一个cyf字符串
String str3 = "AAD@#$cyf";
String str4 = "AAD@#$cyfcyfcyfcyfcyf";
String regex3 = "^[A-Z]{2,4}\\W+(cyf)$"; //2到4个大写字母 然后 紧跟至少一个非单词字符 并 以一个cyf结尾
String regex4 = "^[A-Z]{2,4}\\W+(cyf)+$"; //同上 但是可以以一个或多个cyf结尾
// 注意:
// [A-Z]{2,4} 是一个整体
// \\W+ 是一个整体
// (cyf)+ 是一个整体
System.out.println(str3.matches(regex3)); //输出结果为:true
System.out.println(str4.matches(regex4)); //输出结果为:true

下面是一些正则表达式的书写范例

1、验证用户名和密码:"^[a-zA-Z]\w{5,15}$""[A-Za-z]_[0-9]"。由数字、字母、下划线组成,并且第一个字必须为字母,长度为:5~152、验证电话号码:"(\d{3,4}-)*\d{7,8}"正确格式:xxx/xxxx-xxxxxxx/xxxxxxxx; 
XXX-XXXXXXX  XXX-XXXXXXXX  XXXX-XXXXXXX XXXX-XXXXXXXX
3、验证身份证号(18位数字):"[1-9]\d{16}(\d|X|x)"37032119950506121X
4、验证Email地址:^\w+(\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$;zhang_san@163.com
5、只能输入由数字和26个英文字母组成的字符串:^[A-Za-z0-9]+$ 、^[\w&&[^_]]$”、^[A-z\d]+ ([A-z]+\d?)$
6、整数或者小数:^[0-9]+\.{0,1}[0-9]{0,2}$   
7、只能输入数字:"^[0-9]*$"
8、只能输入n位的数字:"^\d{n}$"
9、只能输入至少n位的数字:"^\d{n,}$"
10、只能输入m~n位的数字:"^\d{m,n}$"
11、只能输入零和非零开头的数字:"^(0|[1-9][0-9]*)$"
12、只能输入有两位小数的正实数:"^[1-9]+(\.[0-9]{2})?$"
13、只能输入有1~3位小数的正实数:"^[0-9]+(.[0-9]{1,3})+$"
14、只能输入非零的正整数:"^+?[1-9]\d*$"
15、只能输入非零的负整数:"^-[1-9][0-9]*$”
16、只能输入长度为3的字符:"^.{3}$"
17、只能输入由26个英文字母组成的字符串:"^[A-z]+$"
18、只能输入由26个大写英文字母组成的字符串:"^[A-Z]+$"
19、只能输入由26个小写英文字母组成的字符串:"^[a-z]+$"
20、验证是否含有^%&',;=?$\"等字符:"[^%&',;=?$\x22]+"
21、只能输入汉字:"^[\u4e00-\u9fa5]{0,}$"
22、验证URL:"^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$"
23、验证一年的12个月:"^(0?[1-9]|1[0-2])$"正确格式为:"01""09""10""12"
24、验证一个月的31天:"^((0?[1-9])|((1|2)[0-9])|30|31)$"正确格式为;"01""09""1""31"
25、获取日期正则表达式:\d{4}[|\-|\.][1-12][|\-|\.][1-31]?

正则表达式的判断条件

// 正则表达式里的判断条件
// 字母数字下划线 组成一个用户名,但是数字不能开头,也不能全是字母 共4-16位

String str = "cyf1071938109";
// (?![a-zA-Z]+$) 判断条件 不是字符串的组成部分
// ?! 表示不能全是这些东西
String usenameRegex = "^(?![a-zA-Z]+$)[a-zA-Z_]\\w{3,15}$";
System.out.println(str.matches(usenameRegex)); //输出结果为:true 
  • Matcher类

    find()方法 尝试找出匹配器中匹配的字符串,返回值为boolean

    String str = "阿萨斯asa啥的asa啥的大无大所asa!";
    String s = "asa";
    // 创建一个正则对象
    Pattern regex = Pattern.compile(s);
    // 正则对象 跟 str 形成一个 匹配器
    Matcher matcher = regex.matcher(str); //创建匹配器对象
    
    int count = 0; //创建计数器
    while(matcher.find()) { //find()尝试查找与该模式匹配的输入序列的下一个子序列
        count++;
    }
    System.out.println("一共有"+count+"个asa!"); //一共有3个asa!
    

Java的国际化

Ø java.util.ResourceBundle:用于加载一个国家、语言资源包。

Ø java.util.Locale:用于封装一个特定的国家/区域、语言环境。

Ø java.text.MessageFormat:用于格式化带占位符的字符串。

为了实现程序的国际化,必须先提供程序所需要的资源文件。资源文件的内容是很多key-value对。其中key是程序使用的部分,而value则是程序界面的显示字符串。

资源文件的命名可以有如下三种形式:

Ø baseName _ language _country.properties

Ø baseName _language.properties

Ø baseName.properties

其中baseName是资源文件的基本名,用户可以自由定义。而language和country都不可随意变化,必须是Java所支持的语言和国家

Java支持的语言和国家

事实上,Java不可能支持所有国家和语言,如需要获取Java所支持的语言和国家,可调用Locale类的getAvailableLocale方法获取,该方法返回一个Locale数组,该数组里包含了Java所支持的语言和国家

下面的程序简单地示范了如何获取Java所支持的国家和语言:

public class LocaleList

{

public static void main(String[] args) 

{

//返回Java所支持的全部国家和语言的数组

Locale[] localeList = Locale.getAvailableLocales();

//遍历数组的每个元素,依次获取所支持的国家和语言

for (int i = 0; i < localeList.length ; i++ )

{

//打印出所支持的国家和语言

System.out.println(localeList[i].getDisplayCountry() + "=" + locale

List[i].getCountry()+ " " + localeList[i].getDisplayLanguage() 

+ "=" + localeList[i].getLanguage());

}

}

}

通过该程序,我们就可以获得Java程序所支持的国家/语言环境。

 

3 完成程序国际化

对于如下最简单的程序:

public class RawHello

{

public static void main(String[] args)

{

System.out.println("Hello World");

}

}

这个程序的执行结果也很简单:肯定是打印出简单的“Hello World”字符串,不管在哪里执行都不会有任何改变!为了让该程序支持国际化,则肯定不能让程序直接输出“Hello World”的字符串,这种写法直接输出一个字符串常量,永远不会有任何改变。为了让程序可以输出不同的字符串,此处绝不可使用该字符串常量。

为了让上面输出的字符串常量可以改变,我们将需要输出的各种字符串(不同国家/语言环境对应不同的字符串)定义在资源包中。

我们为上面程序提供如下两个文件:

第一个文件:mess_zh_CN.properties,该文件的内容为:

#资源文件的内容是key-value对。

hello=你好!

第二个文件:mess_en_US.properties,该文件的内容为:

#资源文件的内容是key-value对。

hello=Welcome You!

对于包含非西欧字符的资源文件,Java提供了一个工具来处理该文件:native2ascii,这个工具可以在%JAVA_HOME%/bin路径下找到。使用该工具的语法格式如下:

native2ascii 源资源文件 目的资源文件

如果我们在命令窗口输入如下指令:

#使用native2ascii命令处理mess_zh_CN.properties文件,生成aa.properties文件

native2ascii mess_zh_CN.properties aa.properties

上面的命令将生成一个aa.properties文件,该文件才是我们需要的资源文件,该文件看上去包含很多乱码,其实是非西欧字符的UNICODE编码方式,这完全正常。将该文件重命名为mess_zh_CN.properties即可。

我们看到这两份文件文件名的baseName是相同的:mess。前面已经介绍了资源文件的三种命名方式,其中baseName后面的国家、语言必须是Java所支持的国家、语言组合。

 

将上面的Java程序修改成如下形式:

public class Hello

{

public static void main(String[] args)

{

//取得系统默认的国家/语言环境

Locale myLocale = Locale.getDefault();

//根据指定国家/语言环境加载资源文件

ResourceBundle bundle = ResourceBundle.getBundle("mess" , myLocale);

//打印从资源文件中取得的消息

System.out.println(bundle.getString("hello"));

}

}

集合的简单总结

一:数组和集合的对比

项目数组集合
长度固定不固定,可以自增
存放的数据类型能存放任意类型只能存放引用类型
同一个数组或集合存放的类型必须相同可以不同,但是一般使用泛型来规定相同
本身类型引用类型引用类型
下标List有,set和Map没有
长度数组.length集合.size()

二.集合体系和特点

  1. Collection体系 和 Map体系

  2. Collection体系 “一个格子存放一个数据” , Map体系 “一个格子存放一个键值对”.

  3. Collection接口下

    • List接口 : 列表 , 有顺序,有下标,可存放重复数据
      • ArrayList: 底层数据结构是顺序表(类似数组) , 遍历快,增删慢
      • LinkedList: 底层数据结构是链表 , 遍历慢, 增删快 .实现的数据结构多
      • Vector: 1.0产物, 线程安全.
    • Set接口 : 集合 , 没有顺序,没有下标,不可存重复数据
      • HashSet: 不能保证元素的排列顺序,顺序有可能发生变化 可以存null
      • LinkedHashSet: 维护了存入和取出顺序
      • LinkedHashSet在迭代访问Set中的全部元素时,性能比HashSet好,但是插入时性能稍微逊色于HashSet
    • Queue : 队列
    • Duque : 双队列
    • SortedSet : 排序接口
      • TreeSet : 可以通过元素的自然排序或比较器进行排序.
  4. Map接口

    • 实现类

      • HashMap : 线程不安全 ,能用null当key或value
      • HashTable : 来自1.0 , 线程安全, 不能用null当key或value
      • LinkedHashMap :维护了键值对的 存如和取出顺序.
      • TreeMap : 排序map,用法跟TreeSet一致.
      • Properties : IO的时候还说 , 以字符串做为键和值
    • 存放KV对, key 唯一 , value 可重复 , 一个key 对应 一个 value

    • 所有的key 可以组成 set , 所有的value可以组成 Collection

三.集合的使用 API级的熟练

行为ListSetMap
add / add(下标,)addput(k,v)
remove(index)remove(指定元素)remove(k)
get(index)无下标,只能用增强循环get(k)
set(下标,)put(k, v)
清空
长度size()size()size()
是不是空集合isEmpty()isEmpty()isEmpty()
包含contains(Object o)
遍历1:普通for没有没有
遍历2:增强for没有
遍历3:迭代器没有
Map遍历1根据map的keyset()方法来获取key的set集合,然后遍历map取得value的值遍历keySet…
Map遍历2使用Map.Entry来获取遍历EntrySet…

注 :LinkdList 可以 实现多种数据接口 , 所以他的API 繁多 , 仔细看.

四:集合工具类 API级

Collections / Arrays(数组工具类)

了解 常用的方法 :

static void**shuffle**(List<?> list) 使用默认随机源对指定列表进行置换。
static <T extends Comparable<? super T>> void**sort**(List<T> list) 根据元素的自然顺序 对指定列表按升序进行排序。
static <T> void**sort**(List<T> list, Comparator<? super T> c) 根据指定比较器产生的顺序对指定列表进行排序。

​ 还有 转为同步集合 转为不可变集合 …

五:练习

  1. 存20个不一样的随机数

  2. 字符串的字母出现次数

  3. 模拟斗地主发牌看牌

  4. 如何将一个列表中的重复元素去掉

    思路:将列表转换为集合,它会自动去重,然后再将集合转换为列表即可

    li1 = [1,2,3,2,1,5,6,7,6,5,8]
    set1 = set(li1)
    li1 = list(set1)
    print(li1)      #结果为:[1, 2, 3, 5, 6, 7, 8]
    

六: 自然排序 和比较器排序

  1. 自然排序的类 需要 实现 lang包下的 Compareable接口.
  2. 比较器排序的类需要实现 util包下的 Comparator接口
  3. 通常和TreeSet / TreeMap / Collections.sort( list ,比较器 ) / Collections.sort( list)

总结

增强for循环使用方便,但性能较差,不适合处理超大量级的数据

迭代器的遍历速度要比增强for循环快很多,是增强for循环的2倍左右

使用entrySet遍历的速度要比keySet快很多,是keySet的1.5倍左右

ArrayList

ArrayList 是可以动态增长和缩减的索引序列,它是基于数组实现的List类

ArrayList的数据结构

分析一个类的时候,数据结构往往是它的灵魂所在,理解底层的数据结构其实就理解了该类的实现思路,具体的实现细节再具体分析

ArrayList的数据结构是:

img

说明:底层的数据结构就是数组,数组元素类型为Object类型,即可以存放所有类型数据。我们对ArrayList类的实例的所有的操作底层都是基于数组的

ArrayList源码分析

img

继承结构解释详见 杂记—>数据结构

**RandomAccess接口:**这个是一个标记性接口,通过查看api文档,它的作用就是用来快速随机存取,有关效率的问题,在实现了该接口的话,那么使用普通的for循环来遍历,性能更高,例如arrayList。

而没有实现该接口的话,使用Iterator来迭代,这样性能更高,例如linkedList。所以这个标记性只是为了让我们知道我们用什么样的方式去获取数据性能更好。

**Cloneable接口:**实现了该接口,就可以使用Object.Clone()方法了。

**Serializable接口:**实现该序列化接口,表明该类可以被序列化,什么是序列化?简单的说,就是能够从类变成字节流传输,然后还能从字节流变成原来的类

ArrayList中储存数据的其实就是一个数组,这个数组就是elementData,在123行定义的 private transient Object[] elementData;

LinkList

HashList

IO流

类 File

在进行文件操作之前,先创建一个File对象

File f = new File("E:/dir") //将电脑中指定路径的文件变成java中的一个对象

API

常用方法

  • boolean createNewFile()
    当且仅当不存在具有此抽象路径名指定名称的文件时,不可分地创建一个新的空文件。
 (如果指定的文件不存在并成功地创建,则返回 true;如果指定的文件已经存在,则返回 false)
  • boolean exists()
    测试此文件对象表示的文件或目录是否存在。
  • boolean mkdir()
    创建此抽象路径名指定的目录。
  • boolean mkdirs()
    创建此抽象路径名指定的目录,包括所有必需但不存在的父目录。
 (加了s表示会把改文件对象的父路径也一起建立)

 ```JAVA
 File c = new File("E:/BBB/CCC/EEE");
 if(!c.exists()) { //如果该对象不存在于外存中
     c.mkdirs(); //创建
 }

​     

- **boolean delete()** 
       删除此抽象路径名表示的文件或目录。 

(文件夹嵌套需要使用"递归删除")


- boolean equals(Object obj) 
      测试此抽象路径名与给定对象是否相等。 

- String getAbsolutePath() 
      返回此抽象路径名的绝对路径名字符串。 

- String getCanonicalPath() 
      返回此抽象路径名的规范路径名字符串。 

- String getPath() 
      将此抽象路径名转换为一个路径名字符串。 

- **boolean isFile()** 
      测试此抽象路径名表示的文件是否是一个标准文件。 

- **boolean isDirectory()** 
      测试此抽象路径名表示的文件是否是一个目录(文件夹)。 

- long lastModified() 
      返回此抽象路径名表示的文件最后一次被修改的时间。 

    注意:为1970年到修改时刻的毫秒值,需要转化 运用Date

  ```java
    File file = new File("E:/BBB/CCC/123.txt");
    System.out.println("文件的最后修改时间:"+new Date(file.lastModified()));  
  • String[] list()
    返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中的文件和目录。
 ```java
 File dir = new File("d:/SteamLibrary");
 //获取dir 根级别的 所有文件夹名字和文件名字
 String[] names = dir.list(); //生成数组
 System.out.println(Arrays.toString(names)); //将数组打印

​     

- File[] listFiles() 
        返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件。 

//获取dir下 根级别 的 所有文件夹对象和文件对象
File[] names = dir.listFiles();
for (File a : names) {
    System.out.print(file.getName()+" ");
}

​     

- 



## 递归删除某文件夹

在日常使用中,当需要删除一个文件夹时,如果直接调用delete(),删除的只是文件夹,如果要连文件夹和里面的内容都删除的话,需要用到**递归删除方法**

```java
// 删除文件夹内所有文件和其本身的递归方法
public static void deleteDir(File dir) {
    //获取dir根目录下 所有 文件对象和文件夹对象
    File[] files = dir.listFiles(); //将要删除的文件夹内的所有文件及文件夹建立一个File数组
    for (File file : files) { //遍历File数组
        if(file.isFile()) { //如果是文件 直接删除
            System.out.println("--> 删除文件:"+file.getName());
            file.delete();
        }else { //如果是文件夹的话,调用自身(方法)来 进入 文件夹来删除
            deleteDir(file);
        }
    }
    System.out.println("==> 删除文件夹:"+dir.getName());
    dir.delete(); //最后删除 自身 文件夹
}

递归查找文件数目

查找某文件夹中所有符合要求的文件数目 运用递归查找方法

import java.io.File;

// 工具类 用来查找指定大小的文件
public class FileFind {
	
	private int total; //所有文件的个数
	private int specialBytes; //指定特殊文件大小 以字节为单位
	private int specialTotal; //记录大于指定大小的文件数
	
	public void find(File dir) { //传入一个文件对象
		//递归查找
		//1:得到根级别的所有文件对象和文件夹对象
		File[] files = dir.listFiles();
		for (File file : files) { //遍历根目录下所有文件对象
			if(file.isFile()) { //如果是文件
				total++;
				if(file.length() >= specialBytes) { //如果该文件大小大于指定大小
					specialTotal++;
				}
			}else { //如果不是文件,则 递归
				find(file);
			}
		}
	}
	
    
   
    //下面是构造方法和封装代码
	public FileFind(int specialBytes) { //构造方法 传入一个文件大小值
		this.specialBytes = specialBytes;
	}
	
	public int getTotal() {
		return total;
	}
	public void setTotal(int total) {
		this.total = total;
	}
	public int getSpecialBytes() {
		return specialBytes;
	}
	public void setSpecialBytes(int specialBytes) {
		this.specialBytes = specialBytes;
	}
	public int getSpecialTotal() {
		return specialTotal;
	}
	public void setSpecialTotal(int specialTotal) {
		this.specialTotal = specialTotal;
	}
	
}

测试类:

public class TestFileFind {

	public static void main(String[] args) {

		FileFind f = new FileFind(1024*1024*3); //查找大于3M的文件
		File file = new File("E:/JavaIO测试文件夹/FindFiles");
		
		f.find(file);
		System.out.println("该文件夹中共有:"+f.getTotal()+"个文件!");
		System.out.println("该文件夹中大于3M的文件共有:"+f.getSpecialTotal()+"个!");

	}
}

IO介绍

IO:输入输出,主要应用于程序和外存(硬盘/网络)中的资源之间进行数据传输

流:概念源自UNIX里的数据管道 理解为“数据流通的管道”,比如 水流 燃气管道 石油管道…

流的分类

A:流向分:
1:输入流 从外界流向java程序
2:输出流 从java程序流向外界

B:流里的数据单元分
1:字节流,数据单元是字节,可以处理一切数据,字节就是2进制
2:字符流,数据单元是字符,只能处理纯文本数据,作用提高处理纯文本数据效率
C:按照直接与数据资源相连接分(文档写角色分)

​ 1:节点流(基本流),直接与数据资源相连接,功能比较简单

​ 2:过滤流(包装流),不直接与数据资源相连接,对某一个节点流进行强化的,功能比较丰富(效 率高。。。) 过滤流一定 持有一个 基本流对象----->设计模式:装饰者模式

D:功能分:打印流 对象流 内存流 随机访问流 合并流…
-------------------------
4个抽象基础类
字节输入流InputStream
—节点流子类FileInputStream
字节输出流OutputStream

​ —节点流子类FileOutputStream

​ 字符输入流Reader
—节点流子类FileReader
字符输出流Writer
—节点流子类FileWriter

字节输入流InputStream

在InputStream里包含如下方法:
(1) int read():从输入流中读取单个字节,返回所读取的字节数据。
(2) int read(byte[] b):从输入流中最多读取b.length个字节的数据,并将其存储在字节数组b中, 返回实际读取的字节数。
(3) int read(byte[] b,int off,int len):从输入流中最多读取len个字节的数据,并将其存储在数组b中,放入数组b中时,并不是从数组起点开始,而是从off位置开始,返回实际读取的字节数。

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

public class IO01 {

	public static void main(String[] args) throws IOException {
		
		//1创建一个输入流 字节输入
		InputStream is = new FileInputStream("job2.sql");
		//2创建一个数组(水桶)
		byte[] b = new byte[1024]; //水桶多大都可以 不一定1024
		int len = -1; //每次中流中读取数据到b里的返回值 -1道标流里已经读完了
		//3循环读
		while((len = is.read(b)) != -1) {
			//len 存放着每次读到的字节个数
			//字节数组--->字符串
			String str = new String(b, 0, len); //最后一读 b极有可能读不满,所以要用len来规定字符串长度
			System.out.println(str);
		}
		//4关闭流
		is.close();
	}
}

PS:

read(byte[] b) 方法

参数:
b - 存储读入数据的缓冲区。
返回:
读入缓冲区的总字节数;如果因为已经到达流末尾而不再有数据可用,则返回 -1。

字符输入流Reader

和上面 字符输入流 的框架一样,但是byte[]数组要换成char[]数组

用的流是

  • 因为Reader是抽象类,不能被new,所以new它的子类FileReader
Reader rd = new FileReader(new File("./abc/aa.txt"));
字节输出流OutputStream

(1) void write(int c/char c):将指定的字节/字符输出到输出流中,其中c既可以表示字节也可以表示字符。
(2) void write(byte[]/char[] buf):将字节数组/字符数组中的数据输出到指定输出流中。
(3) void write(byte[]/char[] buf,int off,int len):将字节数组/字符数组中从off位置开始,长度为len的字节/字符输出到输出流中。

因为字符流直接以字符作为操作单位,所以Writer可以用字符串来代替字符数组,即以String对象作为参数。

Writer里还包含了如下两个方法。
(1) void write(String str):将str字符串里包含的字符输出到指定输出流中。
(2) void write(String str,int off,int len):将字符串从off位置开始,长度为len的字符输出到指定输出流中。

public static void main(String[] args) throws Exception {
    OutputStream os = new FileOutputStream(new File("./abc/aa.txt"));
    byte[] b = {55,56,57,58};
    os.write(b);
    os.close();
}

字符输出流Writer
  • 因为Reader是抽象类,不能被new,所以new它的子类FileWriter

方法和上面字节输出流共用

如果希望直接输出字符串的内容,即使用Writer会有更好的效果

public static void main(String[] args) throws Exception {
    Writer writer = new FileWriter(new File("./abc/aa.txt"));
    char[] ch = {'一','二','三','四','五','六','七'};
    writer.write(ch);
    writer.write(Arrays.toString(ch));
    writer.close();
}

使用IO流来实现文件复制

使用IO流来实现文件的复制,首先需要:

一个输入流:用来将待复制文件输入Java程序

一个输出流:用来将文件从Java程序写入复制区域

最后一定记得:**关闭流 **先开的后关,后开的先关

  • PS:输出流方法常用

void write(byte[] b, int off, int len)
将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。

(将数组 b 中的某些字节按顺序写入输出流;元素 b[off] 是此操作写入的第一个字节,b[off+len-1] 是此操作写入的最后一个字节。)

示例代码:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.DecimalFormat;

public class Copy {

	public static void main(String[] args) throws Exception {
		//视频文件 使用字节流
		
        //1:创建文件对象
		File f01 = new File("E:/JavaIO测试文件夹/待复制视频.mp4");
		File f02 = new File("F:/IO练习/复制视频.mp4"); //这个文件对象用来存放复制视频,在复制完成前这个文件不是实体
		
        //2:创建流
		InputStream is = new FileInputStream(f01); //建立一个字节输入流,指向被复制文件
		OutputStream os = new FileOutputStream(f02); //建立一个字节输出流,指向复制到的文件
		
        //3:定义变量
		int flag = -1; //存储水桶大小
		long count = 0;
		double num = 0; //用来作为进度条
		byte[] b = new byte[1024*2]; //创建一个数据缓冲区 水桶
		
		//4:开始复制
		while((flag=is.read(b)) != -1) {
			os.write(b, 0, flag); //根据每个 水桶数组 装了多少数据来输出
			
             count += flag; //记录已复制了多少字节
			num = (double)count/f01.length();
			DecimalFormat df = new DecimalFormat("0.000%"); //进度条百分比化
			
             System.out.println("复制已完成"+df.format(num));	
		}
		
		//5:关闭流 先开的后关,后开的先关
		os.close();
		is.close();
	}
}

缓冲流

掌握缓冲流:java提供了4个包装流 带缓冲区的 用来提高读写效率和其他功能
1:BufferedInputStream : 提供了缓冲区功能
2:BufferedOutputStream : 提供了缓冲区功能和 flush缓冲区的方法
3: BufferedReader : 提供了缓冲区,redLine读一行
4: BufferedWriter : 提供了缓冲区,newLine 换行

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;

public class BufferDemo {
    
	public static void main(String[] args) throws Exception {
		BufferedReader br = new BufferedReader(new FileReader("name.txt")); //装饰者模式:需要在缓冲流中扔一个被 装饰 的流
		String line = null;
		while((line=br.readLine()) != null) {
			System.out.println(line);
		}
		br.close(); //只需要关闭包装流
	}
}

内存流

待补充

GUI

Java提供了三个包做GUI开发

java.awt 包 – 主要提供字体/布局管理器

javax.swing 包[商业开发常用] – 主要提供各种组件(窗口/按钮/文本框)

java.awt.event 包 – 事件处理,后台功能的实现

AWT

待补充

Swing组件

如图所示:swing组件主要可分为三个部分:

(1)顶层容器::常用有JFrame,JDialog

(2)中间容器:JPanel,JOptionPane,JScrollPane,JLayeredPane 等,主要以panel结尾

(3)基本组件:JLabel,JButton,JTextField,JPasswordField,JRadioButton 等

img

顶层容器

#组件描述
1JFrame一个普通的窗口(绝大多数Swing图形界面程序使用JFrame作为顶层容器)
2JDialog对话框

中间容器

#组件描述
1JPanel一般轻量级面板容器组件(作为JFrame中间容器)
2JScrollPane带滚动条的,可以水平和垂直滚动的面板组件
3JSplitPane分隔面板
4JTabbedPane选项卡面板
5JLayeredPane层级面板

基本组件

#组件描述
1JLabel标签
2JButton按钮
3JRadioButton单选按钮
4JCheckBox复选框
5JToggleButton开关按钮
6JTextField文本框
7JPasswordField密码框
8JTextArea文本区域
9JComboBox下拉列表框
10JList列表
11JProgressBar进度条
12JSlider滑块

各组件API级简介

JFrame组件
JFrame frame = new JFrame(“HelloWorldSwing”);创建及设置窗口
frame.setDefaultLookAndFeelDecorated(true);确保一个漂亮的外观风格
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);设置默认的关闭窗口
frame.pack();显示窗口
frame.setVisible(true);一般放在最后,不然会出现视图看不到的情况
frame.setBounds(600, 300, 500, 400);设置窗口的x,y位置,窗口大小x,y
frame.add(panel) ;添加panel面板到容器
frmIpa.getContentPane().add(panel, BorderLayout.NORTH);添加面板到主窗口,布局在北面
frmIpa.getContentPane().add(scrollPane,BorderLayout.CENTER);添加可滚动面板到主窗口,布局在中间
设置图标

setIconImage(image); 传入一个图片对象

Panel组件
JPanel
JPanel panel = new JPanel();创建面板容器
panel.add(button);添加按钮到面板
JOptionPane
组件功能
JOptionPane.showMessageDialog(panel3, “没有选中任何文件”, “提示”, JOptionPane.WARNING_MESSAGE);弹出提示框到panel容器
JScrollPane
JScrollPane scrollPane = new JScrollPane();创建可滚动面板
scrollPane.setViewportView(textArea);设置面板内容
功能组件
JLabel
组件功能
JLabel label = new JLabel(“Hello World”);添加标签
JButton
JButton button = new JButton(“选择文件”);创建按钮
button.addActionListener(new ActionListener() {}添加操作按钮后的事件监听器
JFileChooser
jfc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES );设置文件对话框
jfc.showSaveDialog(frmIpa);显示打开的文件对话框
jfc.getSelectedFile();获取选择器选择的文件
JTextArea
JTextArea textArea = new JTextArea();创建文本区域
textArea.setText(content);设置内容
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值