java复习Api、集合

Api

object

对于同String方法 返回的是对象的地址值 对于我们没有任何意义 因此我们一般重写掉默认的同String() 方法;

重写标准:我们一般返回对象中所有属性的字符串

== 比较运算符 基本类型比较的是数值

而引用数据类型比较的是两个引用中的地址值

String类重写了equals方法 比较的是两个字符串内容是否相同 如果相同返回true 如果不同返回false

String

String类代表字符串 它的值在创建之后就不能被更改(双引号括起来的值) 再次赋值只不过是改变了str引用指向的对象

String str =“abc”;

String str = "def";//此时 str指向def

String 已经重写了toString 方法

equals 方法 也是被重写了 比较的不是地址值 而是内容··

对于String定义的常量 会存在于方法区中的常量池 比如 "abc" 若已经存在 则不会再次创建 会引用这个地址值 ===day15 String类中查找内存分析图 String类面试题

== 比较运算符 比较的是地址值

equals比较的是值

面试题 重点

String类面试题二

String 类的面试题

  1. 常量池:他是方法去的一块空间,它只存储常量(基本类型常量和字符串常量)

  2. == 与equals方法

String内的方法

String(char [] value):分配一个新的String ,使其表示字符数组中的字符转换为一个新的字符串

String(char[] value , int offset, int count)

从chars的某个索引到某个索引转换为字符串

char[] tocharArray() 将字符串转换为一个新的字符数组

char [] chars = str.tocharArray(); 可以用来遍历

String toLowerCase() 有返回值 将字符串转换为小写

String toUpperCasee() 转换为大写

boolean startsWith(String prefix) 测试字符串是否以指定的前缀开始

boolean endsWith(String suffix) 是否以指定的后缀结束

public boolean contains(CharSequence s) 判断字符串中是否包含 s子串

public boolean equalsIgnoreCase (String anotherString) 将String与另一个String比较 不考虑大小写 判断长度是否相同

String substring(int beginIndex, int endIndex) 截取字符串 (含头不含尾)

常用Api

StringBuilder 就是一个字符串容器 里面可以存储字符串

StringBuilder sb = new StringBuilder("lonsk")//容器中有lonsk

append 方法 添加方法

delete 方法 直接在容器中删除

StringBuilder 存储原理

append() 添加的所有数据类型的数据都会编程一个个字符 追加到底层value 字符数组中

  1. 最终当调用sb.toString() ,会把字符数组中的所有字符转换为一个字符串

  2. 如果追加的内容超过默认长度16,那么此时会在创建一个新的字符数组new char[2*原始长度+2]

  3. 再把原字符数组中的内容拷贝到新数组中去

  4. char【】 value = new char [2*原始数组长度]

  5. 链式编程:StringBuilder的append方法的返回值是原容器

  6. 个人理解 :其实就是一个字符串容器 里面有很多方法

StringBuilder类和StringBuffer类

相同点:StringBuilde和StringBuffer里面的构造方法和成员方法基本一致使用方法也基本一致

不同点:

StringBuilder是线程不安全的,效率高

StringBuilder是线程安全的,效率低

Date 类成员方法

long getTime() 返回自1970年1月1日 到当前时间的毫秒值’

用途:

long starTime = new Date().getTime();
for (int i = 0; i < 100000; i++) {
    i = i+100;
}
long endTime = new Date().getTime();//可以算出运行时间
System.out.println(starTime-endTime);//该时间与电脑cpu有关

lovalDate类

里面封装的只有年月日,而且默认格式为年-月-日

获取方法:

static LocalDate now()

LocalDate now = LocalDate.now();
System.out.println(now);//2024-02-20
System.out.println(now.getYear());//2024
System.out.println(now.getMonth());
System.out.println(now.getDayOfMonth());
​

可以更改时间

System.out.println(LocalDate.now());
LocalDate now = LocalDate.of(2019,2,3);//如果不需要系统时间 那么可以设置时间
System.out.println(now);

plus增加 年月日

LocalDate now  = LocalDate.now();
LocalDate now2 = now.plusYears(3);//增加三年
System.out.println(now2);
System.out.println(now.isLeapYear());//判断当年是否是闰年
System.out.println(now2.withYear(2018).isLeapYear());//更改年份且判断是否为闰年

判断时间是否相同

LocalDate now = LocalDate.now();
LocalDate now2 = LocalDate.of(2031,2,3);
System.out.println(now.isEqual(now2));//判断时间是否相同

LocalDateTime类

同上

LocalDateTime now = LocalDateTime.now();
System.out.println(now);//2024-02-20T22:13:24.893962500

of with plus 判断语句 isEqual()

日期和字符串的相互转换

jdk1.8版本之前的方法

Date date = new Date();
System.out.println(date);
​
SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss");
String formatStr = sdf.format(date);
System.out.println(formatStr);

之后的方法

LocalDateTime now  = LocalDateTime.now();
 System.out.println(now);//2024-02-20T22:50:43.854212100
 DateTimeFormatter df = DateTimeFormatter.ofPattern("YYYY-MM-dd HH:mm:ss");
 System.out.println(df.format(now));//2024-02-20 22:50:43

LocalDate , LocalTime , LocalDateTime 中都有以下两个方法

static LocalDateTime parse(CharSequence text)

static LocalDateTime parse(CharSequence text,DateTimeFormatter formatter)

LocalDate now = LocalDate.now();
System.out.println(now);
LocalDate parse = LocalDate.parse("2012-10-12");//将字符串转换为日期对象
System.out.println(parse.getYear());

可以按照指定的模式改变字符串

LocalDate now = LocalDate.now();
System.out.println(now);
LocalDate parse = LocalDate.parse("2012-10-12");//将字符串转换为日期对象
System.out.println(parse.getYear());
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy/MM/dd");//改变字符串日期模式
LocalDate parse1 = LocalDate.parse("2012/10/12",df);
System.out.println(parse1.getDayOfMonth());

时分秒类 年月日时分秒类方法同上

正则表达式

正则表达式其实是一种专门用来匹配字符串的规则

而且这个规则也是一个字符串

String 类

boolean matches(String regex) 告知此字符串是否匹配给定的正则表达式

[规则] 表示这个字符串只有一位

[abc] a或b或c

[^abc] 除了abc之外的一个字符

[a-zA-Z] a到z 或 A到Z 两头的字母包括在内

System.out.println("abc".matches("abc"));//true
System.out.println("abc".matches("ab"));//false
System.out.println("ab".matches("[abc]"));//false
System.out.println("ab".matches("[abc][ab]"));//true
System.out.println("d".matches("[^abc]"));//true
System.out.println("Aa".matches("[a-zA-Z][a-zA-Z]"));//true

预定义字符类

.任何字符 (与行结束符可能匹配也可能不匹配

\d数字[0-9]

\w单词字符[a-zA-Z_0-9]

System.out.println(".".matches("\\."));
System.out.println("1".matches("\\w")); //需要转义字符加持

正则表达式数量词 Boolean 类型

X? X出现一次或0次

X* X出现0次或者多次

X+ X出现一次或者多次

X{n} X 出现n次

X{n,} X至少出现n次

X{n,m} X至少出现n次但是不能超过m次

//手机号匹配规则
        String regexStr = "1[34578]\\d{9}";
        System.out.println("13837808450".matches(regexStr));
        System.out.println("12837808450".matches(regexStr));//false
        //邮箱匹配规则
        String regexStr1 = "\\w+@\\w+\\.\\w+";
        System.out.println("chang@123.com".matches(regexStr1));

正则分割方法

//String[] split();  正则匹配分割模式 并返回字符串数组类型
String str = "I  love you forever";
String[] strings = str.split(" +");
for (int i = 0; i < strings.length; i++) {
    System.out.println(strings[i]);
}

字符串替换方法

replaceAll(String regex, String replacement)

自动装箱 自动拆箱

自动拆箱:将基本类型包装类转化为基本类型

自动装箱:将基本类型转换为对应的基本类型包装类

Integer i = 13;//  基本数据类型  装箱Integer i = Integer.valueOf(13)
i += 3;
                // i=13;=>拆箱  i.intValue() => 13+3 = 16;
                //将16转化为对应的包装类(装箱) i = Integer.valueof(16);
                //也相当于 i= new Integer(16);

装箱的缓存机制

: 如果 装箱的整数值在-128 -- 127(byte 取值范围) ,那么装箱的时候就会使用同一个Integer 对象 也就是说用的是同一个地址;

例子

	Integer i1 = 300;
	Integer i2 = 300;
    System.out.println(i1 == i2);//false
    System.out.println(i1.equals(i2));//true

    Integer i3 = 126;
    Integer i4 = 126;
    System.out.println(i3 == i4);//true
    System.out.println(i3.equals(i4));//true

Random类

random.nextInt()方法

 Random random = new Random();
        int i = random.nextInt(10);//随机产生一个[0-10)不包含是10的整数
        for (int j = 0; j < 10; j++) {
//            int i = random.nextInt(10);
            System.out.println(i);
        }

随机验证码案例:

//随机四位验证码案例
        char ch = 'a';
        char[] chars = new char[26];
        for (int i = 0; i < 26; i++) {
            chars[i] = ch++;
        }
//        for (int i = 0; i < 26; i++) {
//            System.out.println(chars[i]);
//        }
        StringBuilder str = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < 4; i++) {
            int anInt = random.nextInt(26);
            str.append(chars[anInt]);
        }
        System.out.println(str.toString());

集合

集合体系

为什么需要集合

存储班级中80个同学的成绩?

手动赋值 数组赋值 不方便

第三种方法 我们可以使用别人写好的类来去存储元素,我们不需要在关系空间不够用的问题,这个类就是集合

Collection //最顶级的父类接口

Person p1 = new Person("李白",18);
Person p2 = new Person("王伟",20);
Collection c = new ArrayList();
c.add(p1); //object o = new Person("李白",18);
c.add(p2);
Person p3 = new Person("李白", 18);
System.out.println(c.contains(p3));//重写Person类方法后返回为true

集合的通用迭代(遍历)方式

Interator iterator() 从集合中获取一个迭代器对象 这个迭代器专门用来遍历集合中的元素

Iterator接口中的方法:

boolean hasNext() 判断集合中是否有遍历的元素,如果有hasNext() 就返回true

object next() 去除当前遍历的元素 并返回该元素

Collection c = new ArrayList();
        c.add("李白");
        c.add("王伟");
        c.add("李四");
        Iterator iterator = c.iterator();//创建迭代器对象
        System.out.println(iterator.hasNext());//判断集合中是否有待遍历元素
//        System.out.println(iterator.next());//相当于单链表
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }

在使用迭代器遍历的过程中 不能使用集合的方法 否则报错ConcurrentModificationException

 Collection c = new ArrayList();
        c.add("abc");
        c.add("def");
        c.add("ghk");
        Iterator iterator = c.iterator();
        while (iterator.hasNext()){
            if (iterator.next().equals("ghk")){
//                c.add("sss");
//                c.remove("ghk");//.ConcurrentModificationException
                //因为在使用迭代器的方法遍历集合时 我们使用了集合的删除添加方法  就会报错
                iterator.remove();//删除迭代器遍历的元素
            }
        }
        System.out.println(c);//[abc, def]

增强for

用途 一般是用来遍历数组和集合;要求集合必须继承或者实现Iterable接口

格式 :for(要遍历的容器中元素类型 变量名: 数组/集合){

//取出元素

}

int[] arr = {1,2,3,4};
for(int ee : arr){
    System.out.println(ee);
}

增强for过程其实还是使用的是迭代器原理

while(){}

Collection c = new ArrayList();
c.add("abc");
c.add(123);
c.add("ef");
for (Object o : c){
    System.out.println(o);//循环过程中存在装箱过程
}

泛型

就是广泛的类型

  1. 类上的泛型。

  2. 方法上的泛型

  3. 接口上的泛型

class Generic<Q>{
        public void method(Q q){
            System.out.println(q);
        }
        }
Generic<String> str = new Generic<String>();
str.method("ssaa");
Generic<Integer> anint = new Generic<Integer>();
anint.method(22);

toString 类型

<T> T[] toArray(T[] a)

将集合中的元素存储到指定的数组中 然后返回装满了集合中的元素的这个数组

Collection<String> strings = new ArrayList<>();
    strings.add("ssa");
    strings.add("ssa2");
    strings.add("ssa3");
    String[] strs = new String[strings.size()];
    strings.toArray(strs);
    for (String a:strs){
        System.out.println(a);
    }
}

接口中泛型

interface Father<T>{}

public class Son<T> implements Father<T>{}

Son<Integer> s = new Son<Integer>();

方法上的泛型

当我们调用该方法传参的时候 方法上的泛型被确定

类上的泛型

当我们创建该类的对象的时候 类上的泛型被确定

类名 引用变量名 = new 类名<指定类型>() ;

泛型的优点

Collection c = new ArrayList();//由于接口上的泛型没有指定类型,所有Collection 中的泛型变量被替换为Object类型 而我们的add方法上的泛型也被替换为Object类型

那么集合中有整形 也有字符串类型 那么就不能单单使用字符串的方法属性

总结 :

  1. 使用泛型可以将运行时期可能出现的问题(强制转换异常)提升到编译时期

  2. 避免强转 可以直接调用集合中元素类型的方法

Arraylist :查询快增删慢

有索引位置;默认一个长度为10的数组 且可以自动扩容 原理同StringBuilder一样 若超过该长度 就会自动开辟一个新数组 且新数组的长度为原长度的1.5倍 并且将原数组元素赋值给新数组

  1. set()方法 //set方法返回的是该索引上原有的元素 执行完set方法会将指定元素替换成指定索引位置元素

remove( int index)

移除此列表中指定位置的元素

E get(int index) 返回此列表指定位置上的元素

  1. Arraylist的三种遍历方法

    存储自定义引用类型

     ArrayList<Person> peopleArraylist = new ArrayList<>();
            Person p1 = new Person("aaa", 17);
            Person p2 = new Person("bbb", 18);
            Person p3 = new Person("ccc", 19);
            peopleArraylist.add(p1);
            peopleArraylist.add(p2);
            peopleArraylist.add(p3);
    //        System.out.println(peopleArraylist);
            for (Person p:peopleArraylist){
                System.out.println(p.getName()+" "+p.getAge());
            }

添加一个字符串到0索引位 该元素之后的元素都要一次往后移动一个位置

如果我们增删一个元素 会导致这个元素后边的所有元素往前或者wang'hou移动 由于大量的移动元素 就会导致Array'list效率低

Linklist :查询慢增删快

addFirst() //头插法

LinkedList<String> l = new LinkedList<String>();
l.addFirst("a");
l.addFirst("b");
l.addFirst("c");
System.out.println(l);//[c, b, a]

addLast()//尾插法

LinkedList<String> l = new LinkedList<String>();
l.addLast("a");
l.addLast("b");
l.addLast("c");
System.out.println(l);//[a, b, c]

getFirst() //取第一个元素

getLast() //最后一个元素

removeFirst() //移除第一个元素并返回

removeLast()//移除并返回末尾元素是

LinkedList底层原理&特点

底层使用双向链表

查询慢 增删块

set接口

  1. HashSet不能存储重复元素

  2. 存储元素的顺序和取元素的顺序不一致

  3. 没有索引,无法通过索引操作集合的元素

    遍历方式

    1 迭代器遍历

            HashSet<String> strings = new HashSet<>();
            strings.add("abc");
            strings.add("abc");
            strings.add("ab");
            strings.add("a");
    //        Iterator<String> iterator = strings.iterator();
    //        while (iterator.hasNext()){
    //            System.out.println(iterator.next());
    //        }

增强for

for (String string : strings) {
        System.out.println(string);
}

当查找时 与数组中的元素一一对比 如果对比成功 说明查找成功 如果数组中所有的元素都不是mn 查找失败

如果匹配字符特别靠后 我们的查找效率比较低

引入哈希算法

哈希 :由于不需要大量元素比较 所以相对于普通算法 效率要高一点

public Int method(元素) {

//这个方法内部会根据元素的值换算出一个数组中的索引 然后返回这个索引

}

将来往数组存储元素都要调用method方法来获取一个索引

存入aa调用method(aa) 假如method(aa)计算出了一个索引为2返回这个索引 此时aa元素就会存储到2索引这个位置

存入ab调用method(ab)计算出一个索引为3返回这个索引 此时ab存储到索引为3位置

如果查找ab就会调用method方法此时获取到3索引 就直接去比较 看是否是ab 如果3索引位置是ab说明查找成功如果不是就失败

HashSet保证唯一性原理

HashSet底层保证存储元素唯一的原理:

新添加的元素与集合已有的元素通过调用hashCode() 方法比较哈希值

如果两个元素的hash值不同,新添加的元素直接存入

如果两个元素的hash值相同

此时需要通过equals方法比较两个元素内容,如果equals返回true,说明两个元素的内容相同,此时新添加的元素不在存入

如果equals方法返回false 说明两个元素内容不同,此时新添加的元素要存入

我们一般要重写equals方法和hashCode方法
@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Person person = (Person) o;
    return age == person.age && name.equals(person.name);
}

@Override
public int hashCode() {
    return Objects.hash(name, age);
}

底层:

LinkedHashSet使用:

特点:可以去除重复元素 (去除重复元素原理和HashSet相同,底层以来hashCode() 与equals() 并且可以保证元素的存取顺序一致)

LinkedHashSet<Person> people = new LinkedHashSet<>();
people.add(new Person("a",19));
people.add(new Person("a",19));
people.add(new Person("b",18));
people.add(new Person("c",19));
System.out.println(people);//[Person{name='a', age=19}, Person{name='b', age=18}, Person{name='c', age=19}]

Map体系

概述:Map<K,V>k代表key v代表value 存储键值对

存储那种具有映射关系的键值对 例如姓名---身份证号

hashMap 保证key唯一底层原理依然是hashCode() 与equals() 方法 保证key的唯一

hashMap中存取的键值对和取出顺序不一定相同

HashMap<Integer, String> stringHashMap = new HashMap<Integer, String>();

put() 添加方法 与add()大致相同 不过却有一个Value类型的返回值 如果当前添加的key与map中已有key都不相同 那么这个put方法返回null

如果当前添加的key与map中已有key重复,那么此时会将key对应的新值覆盖掉老值,同时返回老值

get(key) 根据key获取对应的值 不存在返回null

int size() 返回键值对的个数

clear() 清空所有键值对

isEmpty()

containsKey(Object key) 判断指定的key是否存在

remove(Object key) 根据key移除map中的键值对 返回该key对应的value

  • 由于map体系中没有获取迭代器的方法 所以map体系不能通过迭代器直接遍历

  • 所以我们考虑将map体系集合转换成Collection 体系集合 那么就可以使用迭代器遍历

    Set<k> keySet() 方法将map中的所有key封装到一个Set集合中 然后返回这个Set集合

     HashMap<String, String> hm = new HashMap<>();
            hm.put("1","a");
            hm.put("2","b");
            hm.put("3","c");
    //        System.out.println(hm);
            Set<String> keys = hm.keySet();
            Iterator<String> iterator = keys.iterator();//获取迭代器
    //        while (iterator.hasNext()){
    //            String key = iterator.next();
    //            System.out.println(key+" "+hm.get(key));
    //        }
            for (String key : keys) {//增强for遍历
                System.out.println(key+" "+hm.get(key));
            }

HashMap第二种遍历方法

entrySet() 方法

HashMap<String, String> hm = new HashMap<>();
hm.put("1","a");
hm.put("2","b");
hm.put("3","c");
Set<Map.Entry<String, String>> entries = hm.entrySet();
System.out.println(entries);//[1=a, 2=b, 3=c]
Iterator<Map.Entry<String, String>> iterator = entries.iterator();//获取迭代器
while (iterator.hasNext()){
    System.out.println(iterator.next());
}
for (Map.Entry<String, String> entry : entries) {
    System.out.println(entry.getKey()+" "+entry.getValue());
}
  • 两种遍历方式

    a. keySet() 遍历

    b. entrySet()遍历

案例:

 HashMap<Integer, Student> students = new HashMap<>();
        Student s1 = new Student(01, "王阳明");
        Student s2 = new Student(02, "王为");
        Student s3 = new Student(03, "李白");
        students.put(s1.getId(),s1);
        students.put(s2.getId(),s2);
        students.put(s2.getId(),s3);
        //for增强
//        for (Integer s:students.keySet()){
//            System.out.println(s+" "+students.get(s));
//        }
        //entrySet() 把键值对封装成node对象
        Set<Map.Entry<Integer, Student>> entries = students.entrySet();
        for (Map.Entry<Integer, Student> entry : entries){
            System.out.println(entry.getKey()+" "+entry.getValue().getName());
        }
        //利用迭代器
        Set<Integer> keys = students.keySet();
        Iterator<Integer> iterator = keys.iterator();
        while (iterator.hasNext()){
            Integer k = iterator.next();
            System.out.println(k+" "+students.get(k));
        }

LinkedHashMap特点

LinkedHashMap使用 保证存储的Key唯一(唯一原理还是依赖hashCode 方法 和equals方法)

linkedHashMap可以保证 key的存取顺序一致

嵌套集合

遍历 从外到内依次遍历

HashMap<String, String> s1 = new HashMap<>();
s1.put("1001", "张三");
s1.put("1002", "李四");
s1.put("1003", "王五");
HashMap<String, String> s2 = new HashMap<>();
s2.put("2004", "无忌");
s2.put("2005", "乔峰");
s2.put("2006", "虚竹");
HashMap<String, HashMap<String, String>> C = new HashMap<>();
C.put("一班", s1);
C.put("二班", s2);
System.out.println(C);
for (String cl :C.keySet()){//C为大集合
    HashMap<String,String> k = C.get(cl);
    System.out.println(k);//k是外部嵌套的两个班级集合
    for (String s:k.keySet()){
        System.out.println(cl+" "+s+" "+k.get(s));
    }
}
  • 可变参数 针对数组来说 不用在创建一个数组了 直接就可以在参数位置上输入值

  • 但是需要注意一点 定义可变参数时 假如有多个参数 比如(int i int...arr) 可变参数一定要定义在最后 因为可变参数会把所有遍历都视为可变参数

    jdk1.5新特性

    类型...变量名 int...arr

    可变参数本质上也是一个数组

创建集合的快速方法 利用ArrayList

省去add方法

ArrayList<String> strings = new ArrayList<>(Arrays.asList("abc", "def", "ced"));

Arrays

Arrays:一个专门操作数组工具类 里面定义了大量的操作数组方法:对数组排序,对数组二分查找。。。

static <T> List <T> asList(T..... a)

asList可以将数组中的元素封装到一个集合中,然后返回这个集合

<T> T[] toArray(T[] a) 将这个集合中的元素封装到指定数组中,然后返回这个数组

ArrayList类中

ArrayList(Collection <? extend E> c) 构造一个包含指定collection 的元素的列表 这些元素是按照该collection 的迭代器返回他们的顺序排列的

通配符

‘泛型限定

? extends E :泛型上限 限制传入的泛型只能为E类型或者E的子类型

? super E: 泛型下限 限制传入的泛型只能为E类型或者是E的父类型

public static void method(ArrayList<? extends Person> al){
    for (Person p :al){
        p.eat();
    }
}
public static void method(ArrayList<? super Person> al){
    for (Person p :al){//此时method方法参数只能传入person类或者object类  此时会报错 
        p.eat();
    }
}

Collection接口 是单列集合的顶级父接口

Collection类 :专门操作集合的工具类,这个类中的大量方法都跟我们的集合相关

static <T> boolean addAll(Collection<? super T> c,T...elements) 将所有指定元素添加到指定collection中

static void reverse(List<?> list) 反转指定列表中元素的顺序

static void shuffle(List<?> list) 使用默认随机源对指定列表进行置换=====随机集合中的元素

  • 20
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值