JavaSE高级1
内部类
内部类概念:
所谓内部类(Inner Class),顾名思义,就是将一个类定义在另一个类的内部。内部的类称之为内部类。
内部类的主要特点:
内部类可以很好的实现隐藏,可以使用protected、private修饰符。
内部类可以直接访问外部类的所有成员,包括私有成员。
外部类不能直接访问内部类的成员,必须首先要建立内部类的对象才可以访问。
内部类可以解决一些问题,比如间接地去实现多继承。可以避免修改接口而实现同一个类中两种同名方法的调用。
|
成员内部类及应用 成员内部类特点: 成员内部类属于外部类的实例成员,成员内部类可以有public,private,default,protected 权限修饰符。在成员内部类中访问外部类的成员方法和属性,要使用“外部类名.this.成员方 法”和“外部类名.this.成员属性”的形式。 创建成员内部类的实例使用 “外部类名.内部类名 实例名 = 外部类实例名.new 内部类构造方法(参数)”的形式。 成员内部类有以下限制: 成员内部类不能和外部类重名。 不能在成员内部类中定义static属性、方法和类(static final形式的常量定义除外)。因为 一个成员内部类实例必然与一个外部类实例关联,static成员完全可以移到其外部类中去。 package com.abc.tzy;
public class MemberInnerClass {
public static void main(String[] args) {
//创建外部类对象
Outer1 outer = new Outer1();
//创建内部类的对象
Outer1.Inner1 inner = outer.new Inner1();
inner.innerShow();
outer.outerShow();
}
}
class Outer1{
private String name = "张三";
private int num1 = 10;
public void outerShow(){
System.out.println(name);
System.out.println(num1);
// System.out.println(num2);//外部类不能直接访问内部类的成员
//外部类要访问内部类成员要先产生内部类对象
//Inner1 in = new Inner1();
//in.innerShow();
}
public class Inner1{//如果内部类为私有的 那么只有外部类自己可以使用,测试类都不能使用
private String name = "李四";
private int num2 = 20;
private static final int num3 =30;//静态常量在内部类中是可以的。
//private static int num3 =30;
//在成员内部类中不能声明静态属性和方法
public void innerShow(){
System.out.println(Outer1.this.name);
System.out.println(name);
System.out.println(num2);
//Outer1.this.outerShow();如果有同名方法就要加外部类名.this.方法名
outerShow();
//成员内部类可以直接访问外部类属性和方法(包括私有)
}
}
}
内部类例1 package com.abc.tzy;
//内部类实现多继承
public class MultiExtendsDemo {
public static void main(String[] args) {
C c = new C();
c.getInstanceA1().showA();
c.getInstanceB1().showB();
c.showA();
c.showB();
}
}
class A{
public void showA(){
System.out.println("A");
}
}
class B{
public void showB(){
System.out.println("B");
}
}
class C{
class A1 extends A{
public void showA(){
super.showA();
}
}
class B1 extends B{
public void showB(){
super.showB();
}
}
public A1 getInstanceA1(){
return new A1();
}
public B1 getInstanceB1(){
return new B1();
}
public void showA(){
new A1().showA();
}
public void showB(){
new B1().showB();
}
}
内部类实现 伪多继承 package com.abc.tzy;
//抽象类和接口中有同名方法,使用内部类去处理
public class Demo {
public static void main(String[] args) {
Son son = new Son();
son.show();
son.show2();
}
}
abstract class Parent{
public abstract void show();
}
interface IShow{
public abstract void show();
}
/*
class Son extends Parent implements IShow{
//到底重写的是哪个不清楚除非把上面的抽象类或者接口方法改了
@Override
public void show() {
}
}
*/
class Son extends Parent{
@Override
public void show() {
System.out.println("重写抽象类里的show方法");
}
private class Inner2 implements IShow{
@Override
public void show() {
System.out.println("重写接口中的show方法");
}
}
public void show2(){
new Inner2().show();
}
}
内部类对同名方法的处理 |
静态内部类及应用 静态内部类特点: 使用static修饰成员内部类叫静态内部类。 静态内部类跟外部类没有任何关系,只是在生成类名和类定义时有影响。 静态内部类可以看作是与外部类平级的类。使用方式与外部类平级的类 完全相同。 创建静态内部类的实例使用: 外部类名.内部类名 实例名 = new外部类实例名.内部类名(参数) 静态内部类有以下限制: 静态内部类不能与外部类重名。 静态内部类不能访问外部类的非静态的属性和方法。外部类不能访问 内部类的非静态的属性和方法。 package com.abc.tzy;
public class StaticInnerClass {
public static void main(String[] args) {
Outer2.Inner2 inner = new Outer2.Inner2();//构造静态内部类对象
inner.innerShow();
System.out.println("*******");
Outer2 outer = new Outer2();
outer.outerShow();
}
}
class Outer2{
private String name = "张三";
private int num1 = 10;
private static int num3 =100;
public void outerShow(){
System.out.println(name);
System.out.println(num1);
Inner2 inner2 = new Inner2();
System.out.println(inner2.name);
System.out.println(inner2.num2);
}
public static class Inner2{
private String name = "李四";
private int num2 = 20;
private static final int num3 =30;
public void innerShow(){
//System.out.println(Outer2.this.name);
//静态内部类不能访问外部类的非静态成员
System.out.println(name);
System.out.println(num2);
System.out.println(num3);
System.out.println(Outer2.num3);
}
}
}
静态内部类实例 |
|
匿名内部类及应用 匿名内部类特点: 匿名内部类是没有名称的内部类,没办法引用它们。必须在创建时, 作为new语句的一部分来声明并创建它们的实例。 匿名内部类必须继承一个类(抽象的、非抽象的都可以)或者实现一个接口。 如果父类(或者父接口)是抽象类,则匿名内部类必须实现其所有抽象方法。 匿名内部类中可以定义代码块,用于实例的初始化,但是不能定义静态代码块。 匿名内部类语法: new interface/superclass(){//类体} 这种形式的new语句声明一个新的匿名类,它对一个给定的类进行扩展, 或者实现一个给定的接口,并同事创建该匿名类的一个新实例。 package com.abc.tzy;
public class AnonymousInnerClass {
public static void main(String[] args) {
Person p = new Person();
Dog d = new Dog();
p.feed(d);
//匿名类
p.feed(new Animal(){
@Override
public void eat() {
System.out.println("吃鱼");
}
});
// 喂同一只狗
Animal dog = new Animal(){
private String name = "aa";
@Override
public void eat() {
System.out.println("啃骨头");
}
public void show(){
System.out.println(name);
}
};
p.feed(dog);
p.feed(dog);
// dog.show();//转成Animal时丢失了方法
new Animal(){
private String name = "aa";
/*static不可以使用*/{
name="哈哈";
}
@Override
public void eat() {
System.out.println("啃骨头");
}
public void show(){
System.out.println(name);
}
}.show();
}
}
class Person{
public void feed(Animal animal){
animal.eat();
}
}
//abstract class Animal{
// public abstract void eat();
//}
//class Dog extends Animal{
// @Override
// public void eat() {
// System.out.println("啃骨头");
// }
//}
//接口和抽象类一样
interface Animal{
public abstract void eat();
}
class Dog implements Animal{
@Override
public void eat() {
System.out.println("啃骨头");
}
}
匿名内部类 |
局部内部类及应用 局部内部类特点: 定义在代码块、方法体内的类叫局部内部类。 局部内部类访问外部类的属性和方法使用“外部类名.this.属性名”和 “外部类名. this.方法名(参数)”的形式。 对外部世界完全隐藏,只能在其作用域内生成对象。 局部内部类有以下限制: 局部类不能加访问修饰符,因为它们不是类成员。 成员内部类访问作用域内的局部变量,该局部变量需要使用final修饰. package com.abc.tzy;
public class LocalInnerClass {
public static void main(String[] args) {
Outer3 outer = new Outer3();
outer.showOuter();
}
}
class Outer3{
private String name = "张三";
private int num1 = 10;
private static int num2 = 20;
public void showOuter(){
final int num4 = 50;
//局部内部类不能加访问修饰符
//Inner3 inner =new Inner3();不可以在这里产生
class Inner3{
private int num3 = 30;
private int num1 = 20;
public void showInner(){
System.out.println(num3);
System.out.println(num1);
System.out.println(Outer3.this.num1);
System.out.println(Outer3.num2);
System.out.println(num4);
//局部内部类只能访问声明其方法中的常量
}
}
Inner3 inner =new Inner3();
inner.showInner();
}
}
局部内部类 package com.abc.tzy;
import java.util.Arrays;
/*开发一个容器来存放键值对
建存放英文名字,值存放中文名字,
对键值对使用内部类进行封装。
1使用静态内部类封装键值对数据;
2容器默认容量为5,超过就扩容其2倍。
3通过调用entryArrays方法返回容器中的数据*/
public class EntryDemo {
public static void main(String[] args) {
MyContainer container = new MyContainer();
container.put("jack", "成龙");
container.put("jay", "周杰伦");
container.put("rose", "玫瑰");
container.put("aa", "小名");
container.put("bb", "小黄");
container.put("cc", "小李");
MyContainer.Entry[] entrys = container.entryArrays();
for (MyContainer.Entry entry : entrys) {
System.out.println(entry.getKey()+entry.getValue());
}
}
}
class MyContainer{
//存放entry对象的数组,默认为5
private Entry [] entrys = new Entry[5];
private int count = 0;
//对外提供一个接口向容器中存放封装好的数据(Entry对象)
public void put(String key,String value){
Entry entry = new Entry();
entry.setKey(key);
entry.setValue(value);
entrys[count++]=entry;//存放entry对象到数组中
if(count>=entrys.length){
//数组的扩容
int newCapacity = entrys.length*2;
//把老数组中的数据复制到长度为newCapacity的新数组中
entrys = Arrays.copyOf(entrys, newCapacity);
}
}
//把容器中有数据的数据返回
public Entry[] entryArrays(){
return Arrays.copyOfRange(entrys, 0, count);
}
//把键值对封装在Entry对象中
public static class Entry{
private String key;
private String value;
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
}
内部类封装案例 |
自动装箱和拆箱(jdk1.5后)
1、有时我们需要将int这样的基本数据类型转换为引用类型对象;
2、基本数据(Primitive)类型的自动装箱、拆箱是J2SE5.0提供的新功能,为打包基本数据类型提供了方便,但提供方便的同时隐藏了西街,
建议在能够区分基本数据类型与引用类型的差别时再使用;
3、一个自动装箱的例子: Integer i = 10; 相当于Integer i = new Integer(10);
①进行编译时,编译器根据语句上下文判断是否进行自动装箱动作。在上例中变量i引用的是Integer类的实例。
②同样的动作使用于boolean、byte、short、 char、 long、 float、double等基本数据类型,分别使用对应的包装类型(Wrapper Types)
Boolean、Byte、Short、character、Long、Float、Double
4、J2SE5.0中也可以自动拆箱(unboxing),也就是将对象中的基本数据类型信息自动取出.
/*例如:*/ Integer m = 10; int n =m ; //相当于 n = m.intValue(); /*m变量在自动装箱为Integer的实例后,如果被赋值给一个int类型的变量 n,则自动转换为int类型在赋值,在做运算的时候也会自动拆装箱。*/
package com.abc.tzy;
public class AutoBoxDemo {
public static void main(String[] args) {
int i = 10;
double d = 10.5;
//把基本类型赋值给引用类型,基本类型会在编译时自动装箱
Integer num1 = i;
Double num2 = new Double(d);//调用这个装箱
System.out.println(num1.intValue());
System.out.println(num2);
//把包装类(引用类型)复制给基本类型,会自动做拆箱
int j = num1;
double k = num2.doubleValue();//调用这个方法拆箱
System.out.println(j);
System.out.println(k);
}
}
自动拆装箱案例
枚举类型
1、public enum Color{
RED,BLUE,BLACK,YELLOW,GREEN
}
①enum很像特殊的class,实际上enum声明定义的类型就是一个类
②这些类都是类库中Enum类的子类(java.lang.Enum<E>),它们继承了Enum中许多有用的方法
2、枚举值都是public static final的,也就是常量,因此枚举类中的枚举值应全部大写。
3、枚举类型是class,在枚举类型中有构造器,方法和字段。但枚举构造器有很大的不同:
①构造器只是在构造枚举值的时候被调用
②构造器私有private,不允许有public构造器
4、枚举可以在switch语句中使用
package com.abc.tzy;
public class EnumDemo {
public static void main(String[] args) {
System.out.println(Color.ABC/* .toString() */);
System.out.println("*****");
Color[] colors = Color.values();
for (Color color : colors) {
System.out.println(color);
}
System.out.println("*****");
System.out.println(Person1.P1);
System.out.println("*****");
Person1[] p = Person1.values();
for (Person1 person1 : p) {
System.out.println(person1);
}
System.out.println("*****");
Person1 p1 = Person1.P4;
switch (p1) {
case P1:System.out.println(Person1.P1);break;
case P2:System.out.println(Person1.P2);break;
case P3:System.out.println(Person1.P3);break;
case P4:System.out.println(Person1.P4);break;
default:System.out.println("没有该对象");
}
}
}
// 大写常量,对象.属性-静态.
// 当jvm去加载使用枚举类的时候,会预先创建多个枚举类型的对象供外部对象来使用
// 加载的时候:public static final Color RED= new Color();
enum Color {
RED, BLUE(), ABC();
// 枚举类型的值必须作为第一条语句出现
/* public不让外面用-不能用 */private Color() {
System.out.println("我是枚举");
}
}
// public static final Person P1= new Person();
enum Person1 {
P1("张三", 14), P2("李四", 14), P3("王武", 14), P4();
private String name;
private int age;
private Person1(String name, int age) {
this.name = name;
this.age = age;
}
private Person1() {
}
public String toString() {
return name + "--" + age;
}
}
枚举
String/StringBuffer/Builder
String:
java语言中的字符串值属于String类,虽然有其他方法表示字符串(如字符数组),但java一般使用String类作为字符串的标准格式,
Java编辑器把字符串值作为String对象;
String对象一旦创建就不能被改变。如果需要进行大量的字符串修改操作,应该使用StringBuffer/Builder类或者字符数组,
最终结果可以被转换成String对象。
package com.eduask.tzy;
public class StringDemo {
public static void main(String[] args) {
// String对象的声明和操作
String S = "我是程序员";// (常用创建方式)
String s1 = "abcd";
String s2 = "abcd";
System.out.println(s1 == s2);// true
System.out.println(s1.equals(s2));// true
// 结论:字符串常量池里面引用
String s = new String("我是程序员");// 不常用方式
String s3 = new String("abcd");
String s4 = new String("abcd");
System.out.println(s3 == s4); // false
System.out.println(s3.equals(s4));// true
// 结论:在内存空间新分配一个存储空间
// 1、String对象是不可变的
// 2、类中每一个看来会修改String值的方法,其实都是创建了新的String对象(包含修改后的字符串内容:如拼接)
// 3、String的只读特性带来效率优化可能
// 4、字符串字面值储存于字符串池中,String对象优先指向该字符串池,避免发生重复的字符串事例
// 5、系统对String的非修改处理效率很高,远远超过另外两个字符串类StringBuffer和StringBuilder(频繁修改就用后面两个类)
/* String常用方法 */
// ①charAt(int index) 返回指定索引处的 char 值。
String content = "Hello,My Friend,You are my best friend";
System.out.println(content.charAt(2));// l
// ②compareTo(String anotherString) 按字典顺序比较两个字符串。
System.out.println(content.compareTo("hello"));// -32
// ③concat(String str) 将指定字符串连接到此字符串的结尾。
content = content.concat("I lied");//content = content+"I lied";
System.out.println(content);//Hello,My Friend,You are my best friendI lied
//④endsWith(String suffix)测试此字符串是否以指定的后缀结束。
System.out.println(content.endsWith("lied"));//true
//⑤startsWith(String suffix)测试此字符串是否以指定的前缀开始。
System.out.println(content.startsWith("Hello,"));//true
//⑥contains(CharSequence s) 当且仅当此字符串包含指定的 char 值序列时,返回 true。
System.out.println(content.contains("My"));//true
//⑦equals(Object anObject) 将此字符串与指定的对象比较。(案例在上面)
//⑧equalsIgnoreCase(String anotherString) 将此 String 与另一个 String 比较,不考虑大小写。
//⑨indexOf(int ch)返回指定字符在此字符串中第一次出现处的索引。
// indexOf(String str, int fromIndex)返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始。
// lastIndexOf(String str)返回指定子字符串在此字符串中最右边出现处的索引。
// lastIndexOf(String str, int fromIndex) 返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索。
System.out.println(content.indexOf("o"));
System.out.println(content.lastIndexOf("o"));
System.out.println(content.indexOf("o",5));//17
//⑩length() 返回此字符串的长度。
System.out.println(content.length());//44
//⑩① replace(char oldChar, char newChar) 返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。
System.out.println(content.replace('e', 'a'));//Hallo,My Friand,You ara my bast friandI liad
//⑩②split(String regex) 根据给定正则表达式的匹配拆分此字符串。
String [] arr = content.split(" ");
System.out.println(arr.length);
for (String string : arr) {
System.out.print(string+"*");//Hello,My*Friend,You*are*my*best*friendI*lied*
}
System.out.println();
//⑩③substring(int beginIndex) 返回一个新的字符串,它是此字符串的一个子字符串。
// substring(int beginIndex, int endIndex) 返回一个新字符串,它是此字符串的一个子字符串。
System.out.println(content.substring(5));//,My Friend,You are my best friendI lied
System.out.println(content.substring(5, 10));//,My F
//⑩④toLowerCase() 使用默认语言环境的规则将此 String 中的所有字符都转换为小写。
// toUpperCase() 使用默认语言环境的规则将此 String 中的所有字符都转换为大写。
System.out.println(content.toLowerCase());//hello,my friend,you are my best friendi lied
System.out.println(content.toUpperCase());//HELLO,MY FRIEND,YOU ARE MY BEST FRIENDI LIED
//⑩⑤trim() 返回字符串的副本,忽略前导空白和尾部空白。
System.out.println(" abc ");// abc (有前后空格)
System.out.println(" abc ".trim());//abc(成功去掉前后空格)
}
}
String说明及常用方法
String常用
StringBuffer:(动态字符串)
StringBuffer 线程安全的可变字符序列。
一个类似于String的字符串缓冲区(字符数组),通过某些方法调用可以改变该序列的长度和内容。
每个字符串缓冲区都有一定的容量。只要字符串缓冲区所包含字符序列的长度没有超出此容量,就无需分配新的内部缓冲区数组。
如果内部缓冲区溢出,则此容量自动增大。
StringBuilder:
从JDK5爱是,为StringBuffer类补充了一个单个线程使用的等价类,即StringBuilder.
与StingBuffer相比,通常应该优先使用StringBuilder类,因为它支持所有相同操作,但由于它不执行同步(不敲门-线程不安全),所以速度更快。
package com.abc.tzy;
public class StringBuilderDemo {
public static void main(String[] args) {
//StringBuilder sb = "abd";//无此种声明方法
//StringBuilder sb1 = new StringBuilder();//默认16个字符大小的容量
//StringBuilder sb2 = new StringBuilder(100);//初始化容量大小的字符串
//StringBuilder sb3 = new StringBuilder("abc");//前三个字符就是abc
StringBuilder sb = new StringBuilder();
sb.append("hello");
sb.append(1);
sb.append(1.5);
sb.append(true);
System.out.println(sb.length());//长度 13
System.out.println(sb.capacity());//容量 16
sb.insert(5, " world ");//插入
System.out.println(sb.toString());//打印字符串hello world 11.5true
System.out.println(sb.length());
System.out.println(sb.capacity());
sb.replace(5,7,"el");//替换从index5开始替换7-5个元素为el
System.out.println(sb.toString());//helloelorld 11.5true
sb.replace(5,10,"el");
System.out.println(sb.toString());//helloeld 11.5true
System.out.println(sb.indexOf("el"));//首次出现的下标 1
System.out.println(sb.reverse());//反转 eurt5.11 dleolleh
}
}
StringBuilder和StringBuffer公用的常用方法
package com.abc.tzy;
import java.util.Arrays;
public class MyStringBuilderDemo {
public static void main(String[] args) {
MyStringBuilder msb = new MyStringBuilder();
msb.append("hello").append(",java").append("1234567");
System.out.println("字符个数"+msb.length());
System.out.println("容量大小"+msb.capacity());
System.out.println("输出字符串"+msb.toString());
}
}
/*答案:
字符个数17
容量大小34
输出字符串hello,java1234567
*/
class MyStringBuilder{
private char [] value;//字符数组
private int count = 0;//字符数组中存放字符的个数
public MyStringBuilder(){
value= new char[16];
}
public MyStringBuilder(int capacity){
value= new char[capacity];
}
public MyStringBuilder(String str){
value= new char[str.length()+16];
}
//得到字符数组中的字符个数
public int length(){
return count;
}
//返回容器的容量大小
public int capacity(){
return value.length;
}
//实现字符串的添加
public MyStringBuilder append(String str){
int len = str.length();//获取要添加的字符串的长度
//确保字符数组能放进去所添加的字符串
ensureCapacity(count+len);
//把要添加的字符串追加到新的指定数组的指定位置后面
str.getChars(0, len, value, count);
count+=len;//元素的个数增加了
return this;
}
private void ensureCapacity(int capacity){
//数据超出容量大小
if(capacity>value.length){
int newCapacity = value.length*2+2;//新字符数组大小
value = Arrays.copyOf(value, newCapacity);
}
}
//把字符数组转换为字符串显示
public String toString(){
return new String(value,0,count);
}
}
自己创建的StringBuilder
常用的一些类
|
Date日期类、simpleDateFormat日期格式类 Date表示特定的时间,精确到毫秒 构造方法: publicDate() public Date(long date) 常用方法: 见案例 DateFormat是日期/时间格式化抽象类, 它以与语言无关的方式格式化并分析 日期或时间。 日期/时间格式化子类(如SimpleDateFormat) 允许进行格式化(也就是日期》文本)、 分析(文本》日期) 构造方法: public SimpleDateFormat() public SimpleDateFormat(String pattern) 常用方法: public final String format(Date date) public Date parse(String source) package com.abc.tzy;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
public class DateDemo {
public static void main(String[] args) {
//Date类常用方法
//toString() 把此 Date 对象转换为以下形式的 String: dow mon dd hh:mm:ss zzz yyyy
//其中: dow 是一周中的某一天 (Sun, Mon, Tue, Wed, Thu, Fri, Sat)。
//getTime() 返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此 Date 对象表示的毫秒数。
//setTime(long time) 设置此 Date 对象,以表示 1970 年 1 月 1 日 00:00:00 GMT 以后 time 毫秒的时间点。
Date date = new Date();
System.out.println(date);
//Fri Oct 06 19:42:01 CST 2017
//星期五 十月 6号 时间 中国标准 2017年
System.out.println(date.getTime());
date.setTime(1507290231111L);//设置时间
System.out.println(date);//Fri Oct 06 19:43:51 CST 2017
//通过日期格式化类来让日期以指定方式输出 DateFormat类
//DateFormat类 常用方法
//getDateInstance() 获取日期格式器,该格式器具有默认语言环境的默认格式化风格。返回static DateFormat
//getDateTimeInstance(int dateStyle, int timeStyle) 获取日期/时间格式器,该格式器具有默认语言环境的给定日期和时间格式化风格。
//getDateTimeInstance() 获取日期/时间格式器,该格式器具有默认语言环境的默认格式化风格。返回static DateFormat
//format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) 将一个 Date 格式化为日期/时间字符串。返回abstract StringBuffer
//getDateTimeInstance(int dateStyle, int timeStyle, Locale aLocale) 获取日期/时间格式器,该格式器具有给定语言环境的给定格式化风格。
DateFormat df1 = null;
DateFormat df2 = null;
DateFormat df3 = null;
DateFormat df4 = null;
df1 = DateFormat.getDateInstance();
df2 = DateFormat.getDateTimeInstance();
System.out.println("Date"+df1.format(date));//Date2017-10-6
System.out.println("DateTime"+df2.format(date));//DateTime2017-10-6 19:43:51
df3 = DateFormat.getDateInstance(DateFormat.FULL, new Locale("zh","CN"));
System.out.println("Date"+df3.format(date));//Date2017年10月6日 星期五
df4 = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL, new Locale("zh","CN"));
System.out.println("Date"+df4.format(date));//Date2017年10月6日 星期五 下午07时43分51秒 CST
//自己设定日期格式SimpleDateFormat();
//parse(String text, ParsePosition pos) 解析字符串的文本,生成 Date。
String strDate = "2010年10月19日 10:11:30.345毫秒";
Date d = null;
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss.SSS毫秒");
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss.SSS毫秒");
try {
d=sdf1.parse(strDate);//把日期字符串中的日期部分抽取出来生成一个Date对象
} catch (ParseException e) {
e.printStackTrace();
}
System.out.println(d);//Tue Oct 19 10:11:30 CST 2010
System.out.println(sdf2.format(d));//让日期以指定模版格式格式化输出为字符串。
//2010年10月19日 10:11:30.345毫秒
}
}
Date-DateFormat-SimpleDateFormat案例 |
Calender日历类 Calendar类是一个抽象类,为特定瞬间与一组诸如 YEAR/MONTH/DAY_OF_MONTH/HOUR等日历 字段之间的转换提供了一些方法,并为操作日历字段 (例如获得下星期的日期)提供了一些方法。瞬间 可用毫秒值来表示,它是距历元(即格林威治 标准时间1970年1月1日的00:00:00.000)的偏移量 与其他语言环境敏感类一样,Calendar提供了一个类 方法getInstance,以获得此类型的一个通用的对象。 Calendar的getInstance方法返回一个Calendar对象, 其日历字段已由当前日期和时间初始化。 package com.abc.tzy;
import java.util.Calendar;
public class CalendarDemo {
public static void main(String[] args) {
//getInstance() 使用默认时区和语言环境获得一个日历。返回 Calendar
Calendar c = Calendar.getInstance();
System.out.println(c);
/*java.util.GregorianCalendar[time=15072970758
* 44,areFieldsSet=true,areAllFieldsSet=true,
* lenient=true,zone=sun.util.calendar.ZoneInfo
* [id="Asia/Shanghai",offset=28800000,
* dstSavings=0,useDaylight=false,transitions=
* 19,lastRule=null],firstDayOfWeek=1,
* minimalDaysInFirstWeek=1,ERA=1,YEAR=2017,
* MONTH=9,WEEK_OF_YEAR=40,WEEK_OF_MONTH=1,
* DAY_OF_MONTH=6,DAY_OF_YEAR=279,DAY_OF_WEEK=6,
* DAY_OF_WEEK_IN_MONTH=1,AM_PM=1,HOUR=9,
* HOUR_OF_DAY=21,MINUTE=37,SECOND=55,
* MILLISECOND=844,ZONE_OFFSET=28800000,
* DST_OFFSET=0]
*/
System.out.println(c.get(Calendar.YEAR));
System.out.println(c.get(Calendar.MONTH)+1);
System.out.println(c.get(Calendar.DATE));
System.out.println(c.get(Calendar.HOUR_OF_DAY));
System.out.println(c.get(Calendar.MINUTE));
System.out.println(c.get(Calendar.SECOND));
c.set(Calendar.YEAR, 2013);
System.out.println(c.get(Calendar.YEAR));
System.out.println(c.getTimeInMillis());
/*答案:
2017
10
6
21
46
1
2013
1381067161038
*/
}
}
Calendar |
|
Math数学工具类 Math类包含用于执行基本数学运算的方法,如绝对值、对数、平方根和三角函数。 它是一个final类,其中定义的都是一些常量和静态方法。 package com.abc.tzy;
public class MathRandomDemo {
public static void main(String[] args) {
/*
Math.abs(参数) 返回绝对值 *
Math.ceil(参数)向上取整
Math.floor(参数) 向下取整
Math.nextAfter(21.2, 22.5) 返回第一个参数和第二个参数之间与第一个参数相邻的浮点数
Math.pow(2, 4) 返回2的4次方的值 *
Math.random() 返回带正号的 double 值,该值大于等于 0.0 且小于 1.0 ****
Math.round(25.5) 四舍五入 返回值为long型或int型 *
Math.sqrt(16) 开正平方根 *
Math.max(a,b) 两个数中间取最大的那个数 *
Math.min(a,b) 两个数中间取最大的那个数 *
*/
System.out.println(Math.floor(10.55));//10.0
System.out.println(Math.floor(-10.55));//-11.0
System.out.println(Math.ceil(10.55));//11.0
System.out.println(Math.ceil(-10.55));//-10.0
System.out.println(Math.pow(2,3));//8.0
System.out.println(Math.round(10.6));
System.out.println(Math.round(10.4));
System.out.println(Math.random()*10);//2.0900889016045596
}
}
Math类 |
Random随机数类 Java中,有三种产生随机数的方法 ①通过System.currentTimeMillis()来获取一个当前时间毫秒数的long型的数字 ②通过Math random()返回一个0-1之间的double值(【0,1)) ③通过Random类来产生一个随机数,这是专业的Random工具类,功能强大 Random类中实现的随机算法是伪随机,即有规则的随机。随即时,随机算法的起 源数字称为种子数(seed),在种子数的基础上进行一定的变换,从而产生需要的 随机数字。相同种子数Random对象,相同次数生成的随机数字相同. 两个构造方法: public Random();种子数不同 public Random(long seed);固定种子数 package com.abc.tzy;
import java.util.Random;
public class RandomGenDemo {
public static void main(String[] args) {
System.out.println("第一次四位验证码如下:\n"+RandomGen.codeGen());
System.out.println("第二次四位验证码如下:\r"+RandomGen.codeGen());
System.out.println("第三次四位验证码如下:\n"+RandomGen.codeGen());
}
}
/*
第一次四位验证码如下:
UYFR
第二次四位验证码如下:
Q0ZF
第三次四位验证码如下:
WSJL
*/
class RandomGen{
//生成四位不重复的验证码
public static String codeGen(){
char[] codeSequence={'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','0','1','2','3','4','5','6','7','8','9'};
Random random = new Random();
StringBuilder sb = new StringBuilder();//动态字符串
int count = 0;
while(true){
// 下标
int index=random.nextInt(codeSequence.length);
char c = codeSequence[index];
//假设取出来的字符在动态字符串中不存在,代表不重复
if(sb.indexOf(c+"")==-1){
sb.append(c);//追加到动态字符串中
count++;
if(count==4){
break;
}
}
}
return sb.toString();
}
}
四位无重复验证码 package com.abc.tzy;
import java.util.Random;
public class MathRandomDemo {
public static void main(String[] args) {
Random random1 = new Random();
Random random2 = new Random(10);
Random random3 = new Random(System.currentTimeMillis());
System.out.println(random1.nextInt());
System.out.println(random2.nextInt());
System.out.println(random3.nextInt());
System.out.println(random1.nextInt(5));
System.out.println(random1.nextBoolean());
System.out.println(random1.nextFloat());
System.out.println(random1.nextDouble());
/*第一次运行结果 第二次运行结果 第三次运行结果
-1318050151 -1298124408 1110696500
-1157793070 -1157793070 -1157793070
1134666820 555078446 598447802
4 1 4
true false false
0.94795996 0.0708338 0.26766557
0.9270111740405302 0.569728290291566 0.38472382086060974
*/
}
}
Random类 |
异常概念
- 什么是异常?
所谓异常就是指在程序运行的过程中发生的一些不正常事件。(如:除0溢出,数组下标越界,所要读取的文件不存在)。
- 异常导致的后果?
Java程序的执行过程中如果出现异常事件,可以生成一个异常类对象,该对象封装了异常事件的信息,并将其被提交给java运行时系统,这个过程称为抛出异常,不处理的话
会直接导致程序直接中断。
- 如何防止程序中断?
设计良好地程序应该在程序异常发生时提供处理这些异常的方法,使得程序不会因为异常的发生而阻断或产生不可预见的结果。
Java的异常是通过两种机制来处理的
捕获:try-catch-finally try:监控区域,执行可能产生异常的代码 catch:捕获、处理异常 finally:善后处理,无论是否发生异常,代码总能执行
抛出:throw,throws throw:手动抛出异常(抛出异常) throws:声明方法可能要抛出的异常(声明异常)
|
try-catch-finally try{}语句块中放的是要检测的java代码,可能有会抛出异常,也可能会正常执行。 catch(异常类型){}块是当Java运行时系统接收到try块中所抛出异常对象时, 会寻找能处理这一异常catch块来进行处理(可以有多个catch块). finally{}不管系统有没有抛出异常都会去执行,一般用来释放资源。除了在 之前执行了System.exit(0);(退出程序) package com.abc.tzy;
import java.util.InputMismatchException;
import java.util.Scanner;
public class ExceptionDemo {
public static void main(String[] args) {
System.out.println("请输入一个数字");
Scanner input = new Scanner(System.in);
double res = 0;
try {
// return; 加了return finally也会执行
// System.exit(0);退出程序 finally不会执行(只有这种情况才不会执行)
int number = input.nextInt();
res = 10 / number;
} /*
* catch (InputMismatchException e) {
* System.out.println(e.getMessage());// 错误信息描述
* e.printStackTrace();// 打印堆栈错误信息 } catch (ArithmeticException e) {
* System.out.println(e.getMessage());// 错误信息描述
* e.printStackTrace();// 打印堆栈错误信息 }
*/catch (Exception e) {
System.out.println(e.getMessage());// 错误信息描述
e.printStackTrace();// 打印堆栈错误信息
} finally {
// 释放资源,比如关闭打开的文件,删除临时文件等。
System.out.println("不管怎么样都打印");
}
System.out.println("结果为:" + (Math.round(res) + ""));
// testTryFinally(null);
testTryFinally("hello");
}
// try可以只和finally或者catch使用(单独)
public static void testTryFinally(String name) {
try {
System.out.println(name.length());
} finally {
System.out.println("end");
}
}
}
// java.util.InputMismatchException输入小数
// java.lang.ArithmeticException 输入0
// java.lang.NullPointerException 参数传null
try-catch-finally |
throw和throws throw用于手动抛出异常。作为程序员可以在任意位置手动抛出异常。 throws用于在方法上标识要暴露的异常。抛出的异常交由调用者处理。 两者区别: ①throw用在方法内,后面跟上要抛出的异常对象 ②throws修饰在方法上,告诉调用者此方法可能会抛出异常,后面跟 上可能要抛出的异常类名 package com.abc.tzy;
public class ExceptionDemo1 {
public static void main(String[] args) {
Bar bar = new Bar();
try {
bar.enter(15);
} catch (IllegalAccessError e) {
System.out.println("错误信息:" + e.getMessage());
}
System.out.println("看看打印不");
}
}
class Bar {
public void enter(int age) /* throws IllegalAccessError写在这里主要是为了告诉调用程序员该方法可能会抛出异常 */ {
// 一般throw和 throws一起使用。好习惯
if (age < 18) {
// 受查异常(必须捕获,不然编译不通过),非受查异常可以不捕获
throw new IllegalAccessError("年龄不合格");
// throw new Exception;//受查异常:不捕获就编译不通过.
} else {
System.out.println("欢迎光临");
}
}
}
// 出现这个错一般是因为访问权限错误,好好看看public,protected和private修饰符
// IllegalAccessError这里是自己创建的非法异常
throw-throws |
|
自定义异常: 常见异常: RuntimeException,IOException,SQLException,ClassNotFoundException InputMismatchException,ArithmeticException,NullPointerException, IndexOutOfException 自定义异常:
package com.abc.tzy;
public class ExceptionDemo2 {
public static void main(String[] args) {
Bar1 bar = new Bar1();
try {
bar.enter(15);
} catch (AgeLessThanEighteenException e) {
System.out.println("错误信息:"+e.getMessage());
}
System.out.println("看看打印不");
}
}
//自定义了一个异常类
class AgeLessThanEighteenException extends Exception{
private String message;//描述异常信息
public AgeLessThanEighteenException(String message){
this.message=message;
}
public String getMessage(){
return message;
}
}
class Bar1 {
public void enter(int age) throws AgeLessThanEighteenException {
if (age < 18) {
throw new AgeLessThanEighteenException("年龄不合格");
} else {
System.out.println("欢迎光临");
}
}
}
自定义异常 package com.abc.tzy;
import java.util.Random;
public class ExceptionTest {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
Worker w = new Worker();
Doctor d = new Doctor();
try {
w.work();
} catch (SickException e) {
d.cure(w);
if(w.getStatus().equals("健康")){
System.out.println("恭喜你");
}else{
System.out.println("我尽力了");
}
}finally{
System.out.println("欢迎下次来本医院就诊");
}
}
}
}
class Worker{
private String status;//状态
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public void work() throws SickException{
Random r = new Random();
int rad = r.nextInt(3)+1;
if(rad==1){
//抛出自定义异常对象
throw new SickException("我有病了");
}else{
System.out.println("身体健康不用治疗");
}
}
}
class SickException extends Exception{
private String message;
public SickException(String message) {
super();
this.message = message;
}
public String getMessage(String message){
return message;
}
}
class Doctor{
public void cure(Worker worker){
Random r = new Random();
int rad = r.nextInt(2)+1;
if(rad==1){
worker.setStatus("健康");
}else{
worker.setStatus("死了");
}
}
}
工作者医生案例 |
泛型
泛型简介:
- 泛型是JDK1.5引入的新特性,也是最重要的一个特性。
- 泛型可以在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的。
- 泛型的原理就是“类型的参数化”,即把类型看作参数。也就是说把所要操作的数据类型看作参数,就像方法的形式参数是运行时传递的值的占位符一样。
- 简单的说,类型变量扮演的角色就如同一个参数,它提供给编译器用来类型检查的信息。
- 泛型可以提高代码的扩展性和重用性。
- 总结:所谓泛型,即通过参数化类型来实现在同一份代码上操作多种数据类型,泛型编程是一种编程范式,它利用“参数化类型”将类型抽象化,从而实现更为灵活的复用。
package com.abcd.tzy;
/*泛型类模版
1、泛型类的类型参数可以是泛型类
2、泛型类可以同时设置多个类型参数
3、泛型类可以继承泛型类
4、泛型类可以实现泛型接口
*/
public class GenericDemo {
public static void main(String[] args) {
GenClass<String> gen1 = new GenClass<String>("超人");
System.out.println(gen1.getData());
GenClass<Integer> gen2 = new GenClass<Integer>(15);
System.out.println(gen2.getData());
}
}
class GenClass <T>{
private T data;
public GenClass(T data) {
super();
this.data = data;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
泛型类模版
package com.abcd.tzy;
/*泛型类模版
1、泛型类的类型参数可以是泛型类
2、泛型类可以同时设置多个类型参数
3、泛型类可以继承泛型类
4、泛型类可以实现泛型接口
*/
public class GenericDemo {
public static void main(String[] args) {
GenClass<String> gen1 = new GenClass<String>("超人");
System.out.println(gen1.getData());//超人
GenClass<Integer> gen2 = new GenClass<Integer>(15);
System.out.println(gen2.getData());
GenClass<GenClass<Student>> gen3 = new GenClass<GenClass<Student>>();
GenClass<Student> gen4 = new GenClass<Student>();
gen4.setData(new Student("张三"));
gen3.setData(gen4);
System.out.println(gen3.getData().getData());//我是张三
System.out.println(gen4.getData());//我是张三
GenClass2<String,Integer> gen5 = new GenClass2<String,Integer>("李四",15);
System.out.println("data1:"+gen5.getData1()+"\tdata2:"+gen5.getData2());//data1:李四 data2:15
}
}
class GenClass2<T1,T2>{
private T1 data1;
private T2 data2;
public GenClass2(T1 data1, T2 data2) {
super();
this.data1 = data1;
this.data2 = data2;
}
public T1 getData1() {
return data1;
}
public T2 getData2() {
return data2;
}
}
//创建一个泛型类
class GenClass <T>{
private T data;
public GenClass() {
super();
}
public GenClass(T data) {
super();
this.data = data;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
class Student{
private String name;
public Student(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "我是" + name ;
}
}
泛型类案例
package com.abcd.tzy;
public class GenericDemo1 {
public static void main(String[] args) {
SubClass<String, Integer> sub = new SubClass<String, Integer>("王五", 20);
System.out.println(sub.show1());// 王五
sub.show2(100);// 100 20
}
}
class SuperClass<T1> {
private T1 var1;
public SuperClass(T1 var1) {
super();
this.var1 = var1;
}
public T1 show1() {
return var1;
}
}
interface IInfo<T2> {
public void show2(T2 var2);
}
class SubClass<T1, T2> extends SuperClass<T1> implements IInfo<T2> {
private T2 var2;
public SubClass(T1 var1, T2 var2) {
super(var1);
this.var2 = var2;
}
public T1 show1() {
return super.show1();
}
@Override
public void show2(T2 var2) {
System.out.print(var2 + "\t");
System.out.println(this.var2);
// System.out.println(var2+this.var2);反映会把类型变成Object类型,固不能相加
}
}
泛型继承和实现
限制泛型可用类型:
1、在定义泛型类别时,默认在实例化泛型类的时候可以使用任何类型,但如果想要限制
使用泛型类型时,只能用某个特定类型或者是其子类型才能实例化该类型时,可以在
定义类型时,使用extends关键字指定这个类型必须是继承某个类,或者实现某个接口
2、当没有指定泛型继承的类型和接口时,默认使用extends Object,所以默认
情况下任何类型都可以作为参数传入.
package com.abcd.tzy;
public class GenericDemo2 {
public static void main(String[] args) {
GenericClass<Dog> dogClass = new GenericClass<Dog>();
dogClass.setObj(new Dog());
dogClass.getObj().eat();//啃骨头
GenericClass1<Cat> catClass = new GenericClass1<Cat>();
catClass.setObj(new Cat());
catClass.getObj().eat();//吃鱼肉
//GenericClass<String> catClass = new GenericClass<String>();
//Type mismatch: cannot convert from GenericClass<Cat> to GenericClass<String>
}
}
//泛型类所接收的参数做了限制,只能接收Animal类型或者Animal的子类类型
class GenericClass<T extends Animal>{//泛型不能实现接口,只能继承接口(接口的实例子类),也不能多继承
private T obj;
public T getObj() {
return obj;
}
public void setObj(T obj) {
this.obj = obj;
}
}
abstract class Animal {
public abstract void eat();
}
class Dog extends Animal {
@Override
public void eat() {
System.out.println("啃骨头");
}
}
class Cat implements Animal1 {
public void eat() {
System.out.println("吃鱼肉");
}
}
interface Animal1{
public void eat();
}
class GenericClass1<T extends Animal1>{//泛型不能实现接口,只能继承接口(接口的实例子类),也不能多继承。Animal1是接口
private T obj;
public T getObj() {
return obj;
}
public void setObj(T obj) {
this.obj = obj;
}
}
限制泛型可用类型
泛型通配声明:
同一泛型类,如果实例化时给定的实际类型不同,则这些实例的类型是不兼容的,不能相互赋值。(包括Object也不兼容);
泛型类实例之间的不兼容性会带来使用的不便。我们可以使用泛型通配符(?)声明泛型类的变量就可以解决这个问题。
泛型通配的方式:
"?"代表任意一个类型
Generic<Boolean>f1 = new Generic<Boolean>();
Generic<?>f=f1;
和限制泛型的上限相似,同样可以使用extends关键字限定通配符匹配类型的上限(上边界通配符):
Generic<Dog> f1 = new Generic<Dog>();
Generic<? extends Animal> f = f1;
还可以使用super关键词将通配符匹配类型限定为某个类型及其父类型(下边界通配符):
Generic<Animal> f1 = new Generic<Animal>();
Generic<? super Dog> f =f1;
package com.abcd.tzy;
public class GenericDemo2 {
public static void main(String[] args) {
GenericClass1<Dog> dogClass = new GenericClass1<Dog>();
dogClass.setObj(new Dog());
dogClass.getObj().eat();//啃骨头
GenericClass1<Cat> catClass = new GenericClass1<Cat>();
catClass.setObj(new Cat());
catClass.getObj().eat();//吃鱼肉
//dogClass=catClass;
//cannot convert from GenericClass1<Cat> to GenericClass1<Dog>
GenericClass1<String> stringClass = new GenericClass1<String>();
stringClass.setObj("ABC");
//无限定通配符的使用
GenericClass1<?> gClass =null;
gClass=dogClass;
((Dog)gClass.getObj()).eat();//gClass是Object类型
gClass=catClass;
((Cat)gClass.getObj()).eat();
gClass=stringClass;
System.out.println(((String)gClass.getObj()));
//上边界限定通配符
GenericClass1<? extends Animal1> subclass =null;
subclass=dogClass;
subclass.getObj().eat();//啃骨头 //Animal1 a = dog
subclass=catClass;
subclass.getObj().eat();//吃鱼肉
//下边界限定通配符
GenericClass1<? super Dog> sClass =null;
GenericClass1<Animal1> anClass = new GenericClass1<Animal1>();
// sClass=catClass;//不可以
sClass=dogClass;
System.out.println(sClass.getObj().getClass());//class com.abcd.tzy.Dog
anClass.setObj(new Animal1() {
@Override
public void eat() {
System.out.println("我是动物接口匿名类");
}
});
sClass=anClass;
System.out.println(sClass.getObj().getClass());//class com.abcd.tzy.GenericDemo2$1
}
}
class GenericClass1<T> {// 泛型不能实现接口,只能继承接口(接口的实例子类),也不能多继承。Animal1是接口
private T obj;
public T getObj() {
return obj;
}
public void setObj(T obj) {
this.obj = obj;
}
}
class Dog implements Animal1 {
@Override
public void eat() {
System.out.println("啃骨头");
}
}
class Cat implements Animal1 {
public void eat() {
System.out.println("吃鱼肉");
}
}
interface Animal1 {
public void eat();
}
泛型通配的方式
package com.abcd.tzy;
import java.util.Arrays;
//要求自定义一个容器,此容器可以存放指定类型的数据。通过泛型来实现
public class GenericDemo3 {
public static void main(String[] args) {
IContainer<String> list = new ArrayList<String>();
for (int i = 0; i < 5; i++) {
list.add("data"+(i+1));
}
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
}
}
//data1
//data2
//data3
//data4
//data5
interface IContainer<T>{
public void add(T obj);//给容器添加数据
public T get(int index);//获取指定下标位置处的元素内容
public int size();//返回容器中元素的的个数
}
class ArrayList<T> implements IContainer<T>{
// private T[] data = new T[10];错误,不能创建泛型数组
private Object[] arrays = null;
private int size = 0;//记录容器中元素的个数s
public ArrayList() {
super();
this.arrays = new Object[10];//初始大小为10
}
public ArrayList(int capacity) {
super();
this.arrays = new Object[capacity];//初始大小为capacity
}
@Override
public void add(Object obj) {
//判断元素的个数是否已经超过了容器的大小,超过了应扩容
ensureCapacity(size+1);
arrays[size++]=obj;//先赋值后运算
}
private void ensureCapacity(int capacity){
if(capacity>arrays.length){
int oldCapacity = arrays.length;//获取原有数组容量的大小
int newCapacity = oldCapacity+(oldCapacity>>1);//扩容为原有1.5倍
arrays= Arrays.copyOf(arrays, newCapacity);//把原有数组数据拷贝到新数组中
}
}
@Override
@SuppressWarnings("unchecked")
public T get(int index) {
return (T)arrays[index];
}
@Override
public int size() {
return size;
}
}
自定义可以存放指定数据的容器
Java集合框架
集合框架:
所谓的框架就是一个类库的集合。集合框架就是一个用来表示和操作集合的统一的架构,它包含了实现集合的接口与类。
集合框架中不同的集合类有各自不同的数据结构,所以在使用中要根据应用的性能要求来选择不同的集合类。
集合类存放在java.util包中。
|
|
Iterable接口和迭代器 Iterable接口 实现该接口允许对象成为foreach“”语句的目标,即该集合对象允许迭代。 类集接口Collection是Iterable的子接口,所以所有类集对象可以迭代访问,而映射Map不行。 方法: Iterato<T> iterator() 功能:返回一个在一组T类型的元素上进行迭代的迭代器。 迭代期是实现了Iterator/ListIterator接口的类的对象,可以通过遍历类集,访问其中的每个元素。 ListIterator扩展了父接口Iterator,允许双向遍历集合,并可以修改和删除元素 |
|
Collection接口 Collection 层次结构 中的根接口。Collection 表示一组对象,这些对象也称为 collection 的元素。 |
|
List、Set、Map接口 List接口扩展了Collection,特点:有序且可重复的 Set接口扩展了Collection,特点:无序且不可重复 映射(map)是一个存储关键字/值(键值对)的对象,给定一个关键字,可 查询得到它的值,关键字和值都可以是对象。映射不是Collection的子接口。 所以它本身不能使用迭代期进行遍历. |
List容器特点:
List容器是有序的Collection(也称为序列)。此接口的用户可以对List容器中每个元素的插入位置进行精确地控制。用户可以根据元素的整数索引(在列表中的位置)访问元素,
并搜索列表中的元素。List容器允许插入重复的值,包括NULL。
ArrayList及常用API
ArrayList--动态数组
ArrayList类扩展AbstractList并实现了List接口
支持可随需增长的动态数组
ArrayList构造方法: ArrayList() ArrayList(collection c) ArrayList(int capacity)
除了继承的方法之外ArrayList常用方法:
package com.abcd.tzy;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class ArrayListDemo {
public static void main(String[] args) {
/*
当我们调用无参数构造方法来构造一个ArrayList对象的时候,它会在内部分配一个初始大小为10的一个Object来型的数组
当添加的数据容量炒锅数组大小的时候,会产生一个新的数据,新的数组大小为原来数组大小的1.5倍,接着把原数组中的数组拷贝到新数组中
*/
List<String> nList = new ArrayList<String>();
//boolean add(E e) 将指定的元素添加到此列表的尾部。
//void add(int index, E element) 将指定的元素插入此列表中的指定位置。
// E set(int index, E element) 用指定的元素替代此列表中指定位置上的元素。
// Iterator<E> iterator() 返回以恰当顺序在此列表的元素上进行迭代的迭代器。 (此方法在其父类AbstractList<E>中)
// int indexOf(Object o) 返回此列表中首次出现的指定元素的索引,或如果此列表不包含元素,则返回 -1。
// boolean remove(Object o) 移除此列表中首次出现的指定元素(如果存在)。
// E remove(int index) 移除此列表中指定位置上的元素。
// int size() 返回此列表中的元素数。
// boolean contains(Object o) 如果此列表中包含指定的元素,则返回 true。
// boolean isEmpty() 如果此列表中没有元素,则返回 true
// void clear() 移除此列表中的所有元素。
nList.add("zhangsan");
nList.add("lisi");
nList.add("wangwu");
nList.add("liliu");
nList.add(1,"jay");
nList.add("jack");
nList.set(0, "aaaa");
System.out.println("使用迭代器对象统一遍历");
Iterator<String> it=nList.iterator();
//Iterator迭代器对象的方法
//boolean hasNext() 如果仍有元素可以迭代,则返回 true。
//E next() 返回迭代的下一个元素。
//void remove() 从迭代器指向的 collection 中移除迭代器返回的最后一个元素(可选操作)。
// E get(int index) 返回此列表中指定位置上的元素。
while(it.hasNext()){
String name = it.next();
System.out.print(name+" ");
//aaaa jay lisi wangwu liliu jack
}
System.out.println();
System.out.println("增强For循环进行遍历");
for (String str : nList) {
System.out.print(str+" ");
//aaaa jay lisi wangwu liliu jack
}
System.out.println();
System.out.println("*********");
System.out.println(nList.indexOf("lisi"));
System.out.println(nList.remove("lisi"));//true
System.out.println(nList.remove(0));//aaaa
System.out.println(nList.size());
System.out.println(nList.contains("zhangsan"));//false
System.out.println(nList.get(0));//jay
System.out.println(nList.isEmpty());//false
nList.clear();
System.out.println(nList.isEmpty());//true
}
}
ArrayList常用方法
package com.abcd.tzy;
import java.util.ArrayList;
import java.util.List;
public class ArrayListDemo1 {
public static void main(String[] args) {
List<Student> stuList = new ArrayList<Student>();
Student s1 = new Student("zhangsan", 10);
Student s2 = new Student("sadasd", 15);
Student s3 = new Student("sisi", 12);
Student s4 = new Student("lisi", 19);
Student s5 = new Student("sf", 20);
stuList.add(s1);
stuList.add(s2);
stuList.add(s3);
stuList.add(s4);
stuList.add(s5);
Student s6 = new Student("sf", 20);
System.out.println(stuList.indexOf(s6));//重写了equals因为姓名和年龄一样,判断为同一对象 4
System.out.println(stuList.contains(s6));//true
System.out.println(stuList.remove(s6));//true
System.out.println(stuList.indexOf(s5));//-1
System.out.println(stuList.size());//4
//说明这几个方法都用到equals比较
}
}
class Student {
private String name;
private int age;
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
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;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
ArrayList原码应用
LinkedList及常用API
LinkedList--链表
LinkedList类扩展AbstractSequentialList并实现List接口
LinkedList提供了一个链表数据结构
LinkedList有两个构造方法: LinkedList() LinkedList(collection c)
除了继承方法之外,LinkedList类还自定义了一些有用的方法用于操作和访问容器中的数据:
package com.abcd.tzy;
import java.util.Iterator;
import java.util.LinkedList;
public class LinkedListDemo {
//LinkedList它内部封装的是双向链表数据结构
//每个借点是一个Node对象,Node对象中封装的是你要添加的元素.
//还有一个指向上一个Node对象的应用和指向下一个Node对象的引用
/*
不同的容器有不同的数据结构,不同的数据结构操作起来性能是不一样的
连接数据结构,做插入、删除的效率比较高,但查询效率比较低(LinkedList)
数组结构,它做查询的时候效率高,因为可以通过下标直接找到元素
但插入和删除效率比较低,因为要做位移操作.(ArrayList)
*/
public static void main(String[] args) {
//boolean add(E e) 将指定的元素添加到此列表的尾部。
//void add(int index, E element) 将指定的元素插入此列表中的指定位置。
// E set(int index, E element) 用指定的元素替代此列表中指定位置上的元素。
// Iterator<E> iterator() 返回以恰当顺序在此列表的元素上进行迭代的迭代器。 (此方法在其父类AbstractSequentialList<E>中)
// E removeFirst() 移除并返回此列表的第一个元素。
// E pollFirst() 获取并移除此列表的第一个元素;如果此列表为空,则返回 null。
LinkedList<String> sList = new LinkedList<String>();
//如果用父类的引用指向子类对象List->LinkedList 那么LinkedList自有的方法不能使用
sList.add("zhansan");
sList.add("lisi");
sList.add("wangwu");
sList.add("rose");
sList.add("mary");
sList.add("jack");
sList.addFirst("aa");
sList.addLast("bb");
Iterator<String> it = sList.iterator();
//Iterator迭代器对象的方法
//boolean hasNext() 如果仍有元素可以迭代,则返回 true。
//E next() 返回迭代的下一个元素。
//void remove() 从迭代器指向的 collection 中移除迭代器返回的最后一个元素(可选操作)。
// E get(int index) 返回此列表中指定位置上的元素。
while(it.hasNext()){
String name = it.next();
System.out.print(name+" ");
//aa zhansan lisi wangwu rose mary jack bb
}
System.out.println();
for(Iterator<String> it1 = sList.iterator();it1.hasNext();){
String name1 = it1.next();
System.out.print(name1+" ");
//aa zhansan lisi wangwu rose mary jack bb
}
System.out.println();
for (String string : sList) {
System.out.print(string+" ");
//aa zhansan lisi wangwu rose mary jack bb
}
System.out.println();
System.out.println(sList.removeFirst());//aa
System.out.println(sList.size());
System.out.println(sList.pollFirst());//zhansan
System.out.println(sList.size());
sList.clear();
System.out.println(sList.pollFirst());//null
}
}
LinkedList常用方法
package com.abcd.tzy;
import java.util.Iterator;
import java.util.LinkedList;
//堆栈后进先出
public class LinkedListDemo1 {
public static void main(String[] args) {
MyStack<String> mystack = new MyStack<String>();
mystack.push("zhangsan");
mystack.push("lisi");
mystack.push("wangwu");
mystack.push("zhaoliu");
mystack.pop();
mystack.pop();
Iterator<String> it = mystack.iterator();
while(it.hasNext()){
System.out.print(it.next()+" ");//lisi zhangsan
}
}
}
class MyStack<T>{
private LinkedList<T> data = null;
public MyStack(){
data=new LinkedList<T>();
}
//压栈的方法
public void push(T obj){
data.addFirst(obj);
}
//出栈的方法
public T pop(){
return data.removeFirst();
}
public Iterator<T> iterator(){
return data.iterator();
}
}
LinkedList模拟堆栈
自建ArrayList及Iterator
package com.tzy.iterator;
public interface Iterator<T> {
public boolean hasNext();//判断是否有下一个元素
public T next();//获取下一个元素的内容
}
interface-->Iterator |
package com.tzy.iterator;
public interface List<T>{
public void add(T obj);//给具体的容器添加元素
public T get(int index);//获取指定位置上的元素
public int size();//获取容器中的元素个数
public Iterator<T> iterator();//获取迭代器
}
interface-->List |
package com.tzy.iterator;
public class ArrayList<T> implements List<T> {
private Object [] obj =null;//声明一个Object类型的数组
private int index;//数组的下标
private int size;//记录数组中元素的个数
public ArrayList() {
super();
obj = new Object[10];
index=0;
size=0;
}
@Override
public void add(T obj) {
this.obj[index++]=obj;//把数据存放到数组中
size++;
}
@SuppressWarnings("unchecked")//压制警告
@Override
public T get(int index) {
return (T) this.obj[index];
}
@Override
public int size() {
return size;
}
@Override
public Iterator<T> iterator() {
return new MyIterator<T>(this);
}
}
class-->ArrayList |
package com.tzy.iterator;
public class MyIterator<T> implements Iterator<T> {
private List<T> list =null;
private int index = 0;//访问到容器中元素的当前下标
public MyIterator(List<T> list) {
super();
this.list = list;
}
//判断是否有下一个元素
@Override
public boolean hasNext() {
return index<list.size();
}
//取出下一个元素
@Override
public T next() {
return list.get(index++);
}
}
class-->MyIterator |
package com.tzy.iterator;
public class Test {
public static void main(String[] args) {
List<String> nameList = new ArrayList<String>();
nameList.add("zhangsan");
nameList.add("lisi");
nameList.add("wangwu");
nameList.add("aa");
nameList.add("bb");
Iterator<String> it = nameList.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
System.out.println("********");
for (int i = 0; i < nameList.size(); i++) {
System.out.println(nameList.get(i));
}
}
}
class-->Test |
Map接口详解
- 映射(map)是一个储存键/值对的对象。给定一个键,可查询得到它的值,键和值都是对象。
- 键必须是唯一的,值可以重复。
- 有些映射可以接收null键和null值,而有的不行。
- 下面的接口支持映射:
| 接口 | 描述 |
| Map | 映射唯一关键字给值 |
| Map.Entry | 描述映射中的元素(关键字/值对)。这是Map的一个内部类 |
| SortedMap | 扩展Map以便关键字按升序保持 |
- Map接口映射唯一键到值
- 键(key)是以后用于检索值的对象。给定一个键和一个值,可以存储这个值到一个Map对象中,以后可以使用对应键检索它
- Map接口定义的方法:(见案例)
- Map.Entry接口代表映射项(键-值对)类型,是Map的嵌套类型(内部接口)
- Map接口定义的entrySet()方法返回包含映射项Entry的集合(Set),集合中元素是Map.Entry类型
- Map.Entry接口定义的方法:(见案例)
HashMap及常用API
- HashMap类是基于哈希表的map接口的实现,并允许使用null键和null值。
- 构造方法:HashMap() HashMap(Map m) HashMap(int capacity) HashMap(int capacity,float fillRato) fillRato最好的值是0.75 重复率和运行是最好的
- HashMap实现Map并扩展AbstractMap,本身并没有增加任何新的方法
- 散列映射不保证它的元素的顺序,元素加入散列映射的顺序并不一定是它们被迭代读出的顺序
package com.abc.tzy;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Set;
public class HashMapDemo {
public static void main(String[] args) {
// V put(K key, V value) 在此映射中关联指定值与指定键。
// Set<K> keySet() 返回此映射中所包含的键的 Set 视图。
//Collection<V> values() 返回此映射所包含的值的 Collection 视图。
// V get(Object key) 返回指定键所映射的值;如果对于该键来说,此映射不包含任何映射关系,则返回 null。
// int size() 返回此映射中的键-值映射关系数。
// boolean isEmpty() 如果此映射不包含键-值映射关系,则返回 true。
// void clear() 从此映射中移除所有映射关系。
//Set<Map.Entry<K,V>> entrySet() 返回此映射所包含的映射关系的 Set 视图。
HashMap<String,String> map = new HashMap<String,String>();
map.put("jay", "张三");
map.put("jay", "李四");//将上一个键一样的对象覆盖了
map.put("rose", "玫瑰");
map.put("mary", "李四");
System.out.println(map);
//{jay=李四, mary=李四, rose=玫瑰}
Set<String> keys = map.keySet();
for (String k : keys) {
System.out.print(k+"___"+map.get(k)+" ");
}
//jay___李四 mary___李四 rose___玫瑰
System.out.println();
Collection<String> values = map.values();
for (String v : values) {
System.out.print(v+" ");
}
//李四 李四 玫瑰
System.out.println();
System.out.println(map.size());//3
//当我们调用put(key,value)方法的时候,首先会把key,value封装到
//Entry这个静态内部类对象中。把Entry对象在添加到数组中。所以我们
//想获取map中的所有键值对,我们只要获取数组中的所有Entry对象,接下来
//调用Entry对象中的getKey(),getValue()方法就能获取键值对。
Set<Entry<String, String>> entrySet = map.entrySet();
for(Entry<String, String> entry:entrySet){
System.out.print(entry.getKey()+"***"+entry.getValue()+" ");
}
//jay***李四 mary***李四 rose***玫瑰 true
System.out.println();
map.clear();
System.out.println(map.isEmpty());//true
}
}
HashMap常用
package com.abc.tzy;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
//字符串出现次数计算器
public class AccountStringDemo {
public static void main(String[] args) {
String [] strs = {"zhangsan","lisi","wangwu","zhangsan","liumang"};
AccountUtil.printData(AccountUtil.account(strs));
}
}
//lisi出现的次数1
//liumang出现的次数1
//zhangsan出现的次数2
//wangwu出现的次数1
class AccountUtil{
public static Map<String,Integer> account(String[] strs){
Map<String,Integer> data = new HashMap<String,Integer>();
for (int i = 0; i < strs.length; i++) {
String str = strs[i];
if(data.get(str)==null){
data.put(str, 1);
}else{
//取出key所对应的值+1
data.put(str, (data.get(str)+1));
}
}
return data;
}
public static void printData(Map<String,Integer> data){
Set<Entry<String, Integer>> entrySet = data.entrySet();
for (Entry<String, Integer> entry : entrySet) {
System.out.println(entry.getKey()+"出现的次数"+entry.getValue());
}
}
}
HashMap案例
注:HashMap调用默认构造方法会产生一个底层长度为16的Entry数组。
int hash = hash(key.hashCode()); 首先调用key的hashCode方法来得到一个整数-哈希码
把哈希码作为参数传到hash函数中来进行运算--散列运算--得到了一个整形
int i = indexFor(hash,table.length); 把散列值和数组的长度来进行运算,最终得到Entry对象要存放到数组的位置(下标);
hashMap内部的结构是数组链表结构。因为不同的key有可能算出来是相同的散列值,根据散列值计算出存放到数组的下标会冲突。
哈希码的产生和使用:
当调用对象的hashCode()方法时就会返回当前对象的哈希码值。支持此方法是为了提高哈希表的性能。
hashCode()的常规协定:
1、在Java应用程序执行期间,在统一对象多次调用hashCode方法时,必须一致地返回相同的整数,前提是将对象进行equals比较时所用的信息没有被修改。从
某一应用程序的一次执行到统一应用程序的另一次执行,该整数无需保持一致。
2、如果根据equals(Object)方法,两个对象是相等的,那么对这两个对象中的每个对象调用hashCode方法都必须生成相同的整数结果。
注:这里说的equals(object)方法指的是Object类中未被子类重写过的equals方法。
3、如果根据equeals(java.lang.Object)方法,两个对象不想等,那么对这两个对象中的任一对象调用hashCode方法不要求一定生成不同的整数结果。但是
程序员应该意识到,为不相等的生成不同整数结果可以提高哈希表的性能。
package com.abc.tzy;
import java.util.HashMap;
import java.util.Map;
public class HashMapDemo1 {
public static void main(String[] args) {
Map<Student,String> map = new HashMap<Student,String>();
map.put(new Student("jay", 15), "张三");
map.put(new Student("lisi", 30), "李四");
map.put(new Student("rose", 20), "玫瑰");
map.put(new Student("lisi", 30), "拉拉");
//重写hashCode和equals后名字和年龄一样会被认为是同一个对象。
System.out.println(map);
System.out.println(map.size());
}
}
class Student{
private String name;
private int age;
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
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;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
hashCode例
TreeMap及常用API
TreeMap类通过使用红黑树实现Map接口
TreeMap提供按排序顺序储存键/值对的有效数段,同时允许快速检索
不像散列映射,树映射保证它的元素按关键字升序排序
TreeMap构造方法: TreeMap() TreeMap(comparator comp) TreeMap(Map m) TreeMap(SortedMap sm)
TreeMap实现SortedMap并扩展AbstractMap,它本身没有定义其他方法
package com.abc.tzy;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
public class TreeMapDemo {
public static void main(String[] args) {
// V put(K key, V value) 在此映射中关联指定值与指定键。
// Set<K> keySet() 返回此映射中所包含的键的 Set 视图。
//Collection<V> values() 返回此映射所包含的值的 Collection 视图。
// V get(Object key) 返回指定键所映射的值;如果对于该键来说,此映射不包含任何映射关系,则返回 null。
// int size() 返回此映射中的键-值映射关系数。
// boolean isEmpty() 如果此映射不包含键-值映射关系,则返回 true。
// void clear() 从此映射中移除所有映射关系。
//Set<Map.Entry<K,V>> entrySet() 返回此映射所包含的映射关系的 Set 视图。
TreeMap<String,String> tmap = new TreeMap<String,String>();
tmap.put("cack", "张三"); // 10 现在有个6往里面插入
tmap.put("jay", "李四"); // / \ 比10小那么和5比较
tmap.put("arose", "玫瑰"); // 5 11 比5大那么和7比较
tmap.put("jay", "王武"); // / \
tmap.put("dary", "李四"); // 3 7 比7小那么放左边
System.out.println(tmap); // /
// 6
//{arose=玫瑰, cack=张三, dary=李四, jay=王武} 排序有顺序乍眼看像是abcd顺序 其实是二叉树放的(红黑树)如上:
Set<Entry<String, String>> entrySet = tmap.entrySet();
for (Entry<String, String> entry : entrySet) {
System.out.print(entry.getKey()+"---"+entry.getValue()+" ");
}
//arose---玫瑰 cack---张三 dary---李四 jay---王武
}
}
TreeMap常用
package com.abc.tzy;
import java.util.Comparator;
import java.util.TreeMap;
public class TreeMapDemo1 {
public static void main(String[] args) {
TreeMap<Person,String> pdata = new TreeMap<Person,String>();
pdata.put(new Person("zhangsan", 15), "张三");
pdata.put(new Person("lisi", 31), "李四");
pdata.put(new Person("rose", 32), "玫瑰");
pdata.put(new Person("zhangsan", 33), "张六");
System.out.println(pdata);
// java.lang.ClassCastException: com.abc.tzy.Person cannot be cast to java.lang.Comparable
//需要实现comparable接口自然比较
//重写排序方法后{com.abc.tzy.Person@659e0bfd=张三, com.abc.tzy.Person@2a139a55=李四, com.abc.tzy.Person@15db9742=玫瑰, com.abc.tzy.Person@6d06d69c=张三}
TreeMap<Person1,String> pdata1 = new TreeMap<Person1,String>(new Comparator<Person1>() {
@Override
public int compare(Person1 o1, Person1 o2) {
/*if(o1.getAge()-o2.getAge()>0){
return 1;
}else if(o1.getAge()-o2.getAge()<0){
return -1;
}
return 0;*/
//按名字排序
//String的方法 : int compareTo(String anotherString) 按字典顺序比较两个字符串。
//return o1.getName().compareTo(o2.getName());
//结果:{com.abc.tzy.Person1@7852e922=李四, com.abc.tzy.Person1@4e25154f=玫瑰, com.abc.tzy.Person1@70dea4e=张六}
//少了一个对象 因为名字一样 值被覆盖了 那么要让名字一样比较age:
if(o1.getName().compareTo(o2.getName())>0){
return 1;
}else if(o1.getName().compareTo(o2.getName())<0){
return -1;
}else{
return o1.getAge()-o2.getAge();
}
}
});
pdata1.put(new Person1("zhangsan", 39), "张三");
pdata1.put(new Person1("lisi", 31), "李四");
pdata1.put(new Person1("rose", 32), "玫瑰");
pdata1.put(new Person1("zhangsan", 33), "张六");
System.out.println(pdata1);
//{com.abc.tzy.Person1@7852e922=张三, com.abc.tzy.Person1@4e25154f=李四, com.abc.tzy.Person1@70dea4e=玫瑰, com.abc.tzy.Person1@5c647e05=张六}
}
}
class Person implements Comparable<Person>{
private String name;
private int age;
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
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;
}
//自定义比较办法
@Override
public int compareTo(Person o) {
if(this.age-o.getAge()>0){
return 1;
}else if(this.age-o.getAge()<0){
return -1;
}
return 0;
}
}
class Person1 {
private String name;
private int age;
public Person1(String name, int age) {
super();
this.name = name;
this.age = age;
}
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;
}
}
TreeMap->Comparator->Comparable
TreeMap的key储存引用类型数据,需要满足一定条件
要么引用类型实现Comparable接口
要么为该TreeMap容器提供实现Comparator接口的比较器对象
Set容器特点:
Set容器是一个不包含重复元素的Collection,并且最多包含一个NULL元素,它和List容器相反,Set容器不能保证其元素的顺序。
最常用的Set接口的实现类是HashSet和treeSet
HashSet及常用API
HashSet扩展AbstractSet并且实现Set接口
HashSet使用散列表(又称哈希表)进行储存---->底层封装了HashMap--->HashMap实例--->哈希表(其实就是操作HashMap的键)
构造方法:HashSet() HashSet(Collection c) HashSet(int capacity) HashSet(int capacity,float fillRatio)
HashSet没有定义任何超过它父类和接口提供的其他方法
散列集合没有确保其元素的顺序,因为散列处理通常不参与排序
package com.abc.tzy;
import java.util.HashSet;
public class HashSetDemo {
public static void main(String[] args) {
// boolean add(E e) 如果此 set 中尚未包含指定元素,则添加指定元素。
// int size() 返回此 set 中的元素的数量(set 的容量)。
//boolean isEmpty() 如果此 set 不包含任何元素,则返回 true。
//Iterator<E> iterator() 返回对此 set 中元素进行迭代的迭代器。
// boolean contains(Object o) 如果此 set 包含指定元素,则返回 true。
//boolean remove(Object o) 如果指定元素存在于此 set 中,则将其移除。
// void clear() 从此 set 中移除所有元素。
HashSet<String> data = new HashSet<String>();
data.add("zhangsan");
data.add("lisi");
System.out.println(data.add("jay"));//true
data.add("jack");
System.out.println(data.add("jay"));//false
System.out.println(data);//[lisi, jay, zhangsan, jack]
HashSet<Student2> stuSet = new HashSet<Student2>();
System.out.println(stuSet.add(new Student2("张三", 12)));
System.out.println(stuSet.add(new Student2("李四", 20)));
System.out.println(stuSet.add(new Student2("张三", 12)));//重写equals和hashCode就是false;
System.out.println(stuSet.size());
}
}
class Student2{
private String name;
private int age;
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 Student2(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student2 other = (Student2) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
HashSet常用
TreeSet及常用API
TreeSet为使用树来进行存储的Set接口提供了一个工具,对象按升序储存,访问和检索很快
在存储了大量的需要进行快速检索的排序信息的情况下,TreeSet是一个很好的选择
构造方法见API
总结:TreeSet的内部操作的底层数据是TreeMap,只是我们操作的是TreeMap的Key
package com.abc.tzy;
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;
public class TreeSetDemo {
public static void main(String[] args) {
TreeSet<Person2> pset = new TreeSet<Person2>();
pset.add(new Person2("chenyi", 12));
pset.add(new Person2("taoer", 22));
pset.add(new Person2("zhangsan", 16));
pset.add(new Person2("lisi", 19));
System.out.println(pset);
//[com.abc.tzy.Person2@659e0bfd, com.abc.tzy.Person2@2a139a55, com.abc.tzy.Person2@15db9742, com.abc.tzy.Person2@6d06d69c]
// java.lang.ClassCastException:
//com.abc.tzy.Person2 cannot be cast to java.lang.Comparable
Iterator<Person2> it = pset.iterator();
while(it.hasNext()){
Person2 p = it.next();
System.out.println(p.getName()+"---"+p.getAge());
}
//chenyi---12
//zhangsan---16
//lisi---19
//taoer---22
System.out.println("************");
TreeSet<Person3> ppset = new TreeSet<Person3>(new Comparator<Person3>() {
@Override
public int compare(Person3 o1, Person3 o2) {
if(o1.getAge()-o2.getAge()>0){
return 1;
}else if(o1.getAge()-o2.getAge()<0){
return -1;
}
return o1.getName().compareTo(o2.getName());
}
});
ppset.add(new Person3("chenyi", 22));
ppset.add(new Person3("taoer", 22));
ppset.add(new Person3("zhangsan", 22));
ppset.add(new Person3("lisi", 22));
Iterator<Person3> it1 = ppset.iterator();
while(it1.hasNext()){
Person3 p = it1.next();
System.out.println(p.getName()+"---"+p.getAge());
}
//chenyi---22
//lisi---22
//taoer---22
//zhangsan---22
}
}
class Person2 implements Comparable<Person2>{
private String name;
private int age;
public Person2(String name, int age) {
super();
this.name = name;
this.age = age;
}
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;
}
@Override
public int compareTo(Person2 o) {
if(this.age-o.age>0){
return 1;
}else if(this.age-o.age<0){
return -1;
}
return 0;
}
}
class Person3 {
private String name;
private int age;
public Person3(String name, int age) {
super();
this.name = name;
this.age = age;
}
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;
}
}
TreeSet常用
Collections类及常用API
Collections-类集工具类,定义了若干用于类集和映射的算法,这些算法被定义为静态方法。(相当于服务数组的Arrays类)
package com.abc.tzy;
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
public class CollectionsDemo {
public static void main(String[] args) {
List<String> nList = new ArrayList<String>();
nList.add("zhangsan");
nList.add("lisi");
nList.add("wangwu");
nList.add("zhaoliu");
nList.add("jack");
nList.add("rose");
System.out.println("操作前");
for (String s : nList) {
System.out.print(s+" ");
}
System.out.println();
System.out.println("交换后");
//swap(List<?> list, int i, int j) 在指定列表的指定位置处交换元素。
Collections.swap(nList, 1, 2);
for (String s : nList) {
System.out.print(s+" ");
}
System.out.println();
System.out.println("反转后");
//reverse(List<?> list) 反转指定列表中元素的顺序。
Collections.reverse(nList);
for (String s : nList) {
System.out.print(s+" ");
}
System.out.println();
System.out.println("自然排序后");
//sort(List<T> list)根据元素的自然顺序 对指定列表按升序进行排序。
Collections.sort(nList);
for (String s : nList) {
System.out.print(s+" ");
}
System.out.println();
System.out.println("二分法查找");
//binarySearch(List<? extends Comparable<? super T>> list, T key) 使用二分搜索法搜索指定列表,以获得指定对象。
System.out.println(Collections.binarySearch(nList, "rose"));
System.out.println(Collections.binarySearch(nList, "abc"));
System.out.println();
System.out.println("打乱顺序");
//shuffle(List<?> list) 使用默认随机源对指定列表进行置换。每次运行都会打乱
Collections.shuffle(nList);
for (String s : nList) {
System.out.print(s+" ");
}
System.out.println();
System.out.println("填充");
//fill(List<? super T> list, T obj) 使用指定元素替换指定列表中的所有元素。
Collections.fill(nList,"aaa");
for (String s : nList) {
System.out.print(s+" ");
}
/*
操作前
zhangsan lisi wangwu zhaoliu jack rose
交换后
zhangsan wangwu lisi zhaoliu jack rose
反转后
rose jack zhaoliu lisi wangwu zhangsan
自然排序后
jack lisi rose wangwu zhangsan zhaoliu
二分法查找
2
-1
打乱顺序
jack zhaoliu wangwu zhangsan lisi rose
填充
aaa aaa aaa aaa aaa aaa
*/
}
}
Collections常用
package com.ab.tzy;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
//sort(List<T> list, Comparator<? super T> c)
//根据指定比较器产生的顺序对指定列表进行排序。
public class ArrayListDemo {
public static void main(String[] args) {
List<Person> data = new ArrayList<Person>();
data.add(new Person("jack", 20, 10));
data.add(new Person("rose", 10, 7));
data.add(new Person("mary", 30, 6));
data.add(new Person("zhang", 50, 8));
data.add(new Person("jay", 20, 12));
Collections.sort(data, new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
if (o1.getAge() - o2.getAge() > 0) {
return 1;
} else if (o1.getAge() - o2.getAge() < 0) {
return -1;
} else {
return o1.getName().compareTo(o2.getName());
}
}
});
for (Person person : data) {
System.out.println(person);
}
// Person [name=rose, age=10, id=7]
// Person [name=jack, age=20, id=10]
// Person [name=jay, age=20, id=12]
// Person [name=mary, age=30, id=6]
// Person [name=zhang, age=50, id=8]
}
}
class Person {
private String name;
private int age;
private int id;
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 int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Person(String name, int age, int id) {
super();
this.name = name;
this.age = age;
this.id = id;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", id=" + id + "]";
}
}
Collections-->ArrayList自定义排序
JavaSE高级1的更多相关文章
- javaSE高级篇4 — 反射机制( 含类加载器 ) — 更新完毕
反射机制 1.反射机制是什么?----英文单词是:reflect.在java.lang包下---这才是java最牛逼的技术 首先提前知道一句话----在java中,有了对象,于是有了类,那么有了类之后 ...
- javaSE高级篇7 — 设计原则和设计模式 — 设计模式慢慢更( 这是思想层次篇 )
1.什么是设计原则? 设计原则就是面向对象的原则嘛,即:OOP原则 换句话说:就是为了处理类与类之间的关系( 包括接口.类中的方法 ) 2.OOP设计原则有哪些? 1).开闭原则:就是指对拓展开放.对 ...
- JavaSE高级之GUI编程
下面主要用到了java中的swing进行界面设计,当然java的GUI不如C#的设计的好看,不过原理还是要会的. 1. GUI Graphical User Interface 用户图形界面 a) 主 ...
- JavaSE高级之集合类
下面的内容是对java中的集合类进行的总结,过段时间会分享java的网路编程,多线程等内容,欢迎批评指正. 1.Java中的集合是用来存放对象的,即集合是对象的集合,对象是集合的元素,java AP ...
- JAVASE高级2
反射概述 什么是反射? 反射的的概念是有smith1982年首次提出的,zhuy主要是指程序可以访问.检测和修改它本身状态或行为的一种能力. JAVA反射机制是运行状态中,对于任意一个类,都能够知道这 ...
- javase高级
静态代理:需要代理对象和目标对象实现一样的接口.同一个接口,一个目标类实现,一个代理类实现,代理类除了目标类的方法还有别的增强方法优点:可以在不修改目标对象的前提下扩展目标对象的功能.缺点:1冗余.由 ...
- javase高级技术 - 泛型
在写案例之前,先简单回顾下泛型的知识 我们知道,java属于强变量语言,使用变量之前要定义,并且定义一个变量时必须要指明它的数据类型,什么样的数据类型赋给什么样的值. 所谓“泛型”,就是“宽泛的数据类 ...
- javase高级技术 - 反射
在说反射之前,必须得先说说java的类加载器,类加载器的定义:将.class文件加载到内在中,并为之生成对应的Class对象. 一般有三种 1 Bootstrap ClassLoader 根类加载器也 ...
- 面试复习题(二)JavaSE高级(未完成)
一.Java中的反射 3.说说你对Java中反射的理解 Java中的反射首先是能够获取到Java中要反射类的字节码,获取字节码有3种办法. class.forName(className) 类名.cl ...
随机推荐
- 01.python基础知识_01
一.编译型语言和解释型语言的区别是什么? 1.编译型语言将源程序全部编译成机器码,并把结果保存为二进制文件.运行时,直接使用编译好的文件即可 2.解释型语言只在执行程序时,才一条一条的解释成机器语言给 ...
- 洗礼灵魂,修炼python(3)--从一个简单的print代码揭露编码问题,运行原理和语法习惯
前期工作已经准备好后,可以打开IDE编辑器了,你可以选择python自带的IDLE,也可以选择第三方的,这里我使用pycharm--一个专门为python而生的IDE 按照惯例,第一个python代码 ...
- 一款优秀的JavaScript框架—AngularJS
AngularJS简介 AngularJS诞生于2009年,由Misko Hevery 等人创建,后为Google所收购.是一款优秀的前端JS框架,已经被用于Google的多款产品当中.Angular ...
- Hibernate中的实体映射
一.一对一映射 如人(Person)与身份证(IdCard) 的关系,即为一对一的关系,一个人只能有一张身份证,一张身份证只能属于某一个人,它们的关系图如下图所示: 在Person实体中添加一个属 ...
- httpd网页身份认证
html { font-family: sans-serif } body { margin: 0 } article,aside,details,figcaption,figure,footer,h ...
- The model backing has changed
其他信息: The model backing the 'WebTopFormContext' context has changed since the database was created. ...
- PHP中include与require的特点和区别说明
引用文件的方法有两种:require 及 include.两种方式提供不同的使用弹性. require 的使用方法如 require("MyRequireFile.php"); . ...
- yii2-swiftmailer入门
1. 安装 用yii 2.0框架,默认会有这个扩展 composer require --prefer-dist yiisoft/yii2-swiftmailer 修改composer.json,re ...
- Java简单知识梳理
1. Java是单根继承结构:每个类都继承于Object类 ,这也就保证了每个对象都具备某些功能 2. Java类权限关键字: public -> protected -> default ...
- Pyquery API中文版
Pyquery的用法与jQuery相同,可以直接参考jQuery API学习.