JAVA刷题记录

JAVA的STL

1.String

//string的创建与初始化
//java中String是只读的,没有办法进行变换,因此需要使用StringBuilder。
String s1 = "Runoob";              // String 直接创建
String s2 = "Runoob";              // String 直接创建
String s3 = s1;                    // 相同引用
String s4 = new String("Runoob");   // String 对象创建
String s5 = new String("Runoob");   // String 对象创建
char[] s={'A','G','C','T'};
String st=String.valueOf(s);
char[] c = str.toCharArray() ``//将字符串转为char数组来进行改变字符内容

img

//String的一些方法
str.length() ``//获取字符串的长度
str.charAt(i) ``//获取第i个字符的内容
str.subString(start)  ``//获取[start,)的字符串
str.subString(start,end) ``//获取[start,end)中的字符串
String.equal() ``//判断两个字符串是否相等

int compareTo(String anotherString);//按字典顺序比较两个字符串。
int indexOf(char ch / String str);//返回指定字符在此字符串中第一次出现处的索引。
int indexOf(char ch / String str, int fromIndex);//返回在此字符串中第一次出现指定字符处的索引,从指定的索引开始搜索。
void isEmpty();//判断字符串是否为空。
//StringBuilder的用法:
除了String中支持的方法外,StringBuilder支持字符的增、删、改。
stringBuilder.append(``"we"``); ``//添加we在词尾
stringBuilder.insert(``0``,``"we"``);``//在0的位置加入后面的内容
stringBuilder.delete(``0``,``1``); ``//删除[0,1)的数据
stringBuilder.deleteCharAt(``0``);
stringBuilder.setCharAt(``0``,``'p'``); ``//在某一个独特位置设置字符
char` `c = stringBuilder.charAt(i);``//查询某个位置上的字符
System.out.println(stringBuilder);
new` `String(stringBuilder);``//用stringBuilder来初始化String

2. 集合(Collection-list-set, Map)

获取长度:

  • java中的length属性是针对数组说的,比如说你声明了一个数组,想知道这个数组的长度则用到了length这个属性
  • java中的length()方法是针对字符串String说的,如果想看这个字符串的长度则用到length()这个方法
  • java中的size()方法是针对泛型集合说的,如果想看这个泛型有多少个元素,就调用此方法来查看

数组和集合存储引用数据类型,存的都是地址值

  • A:集合的由来

    • 数组长度是固定,当添加的元素超过了数组的长度时需要对数组重新定义,太麻烦,java内部给我们提供了集合类,能存储任意对象,长度是可以改变的,随着元素的增加而增加,随着元素的减少而减少
  • B:数组和集合的区别

    • 区别1 :
      • 数组既可以存储基本数据类型,又可以存储引用数据类型,基本数据类型存储的是值,引用数据类型存储的是地址值
      • 集合只能存储引用数据类型(对象)集合中也可以存储基本数据类型,但是其实是在存储的时候会自动装箱变成对象
    • 区别2:
      • 数组长度是固定的,不能自动增长
      • 集合的长度的是可变的,可以根据元素的增加而增长,1.5倍增长(部分集合底层也是用数组来做的)
  • C:数组和集合什么时候用
    * 如果元素个数是固定的推荐用数组
    * 如果元素个数不是固定的推荐用集合

img

img

2.1 Collection

int size()//获取集合中元素的个数
boolean add(E e);//添加元素
boolean remove(Object o)//删除指定元素
void clear()//清空集合
boolean contains(Object o)//是否包含
boolean isEmpty()//判断集合是否为空

//All
boolean addAll(Collection c)
boolean removeAll(Collection c)//删除的是交集
boolean containsAll(Collection c)//可以有重复的
boolean retainAll(Collection c)//取交集,并把交集赋值给调用者,若交集为空,调用者也被赋值为空,值改变了所以返回true,只要调用者值改变了就返回true(包括交集为空),否则返回false(调用者是被调用者的子集)
//集合专属的遍历方式:迭代器
Iterator<E> iterator();//返回该集合的迭代器
boolean hasNext();
E next();//返回下个元素,同时迭代器会向下一个走
void remove();//删除该点

增强For循环

int[] arr = {1,2,3};
for(int e:arr){
    System.out.println(e);
}
//Format
for(E e: arr/Collection){
    e.method();
}

2.1.1 List

称为有序集合(序列),可重复

//List特有方法
void add(int index,E e);
E remove(int index);
E set(int index, E e);
E get(int index);
  1. LinkedList

    void addFirst(E e);
    void addLast(E e);
    E getFirst();
    E getLast();
    E removeFirst();
    E removeLast();
    
  2. ArrayList

List扩容机制:

List arrayList = new ArrayList();

如果像上面这样使用默认的构造方法,初始容量被设置为10

装载因子:当前元素个数达到容量*装载因子时,触发扩容,Arraylist装载因子为1

当ArrayList中的元素超过10个以后,会重新分配内存空间,使数组的大小增长到15。

扩容增量:原容量的 0.5倍,ArrayList之外的基本上都是翻倍

可以通过调试看到动态增长的数量变化:10->15->22-...

ArrayList每次扩容都是通过Arrays.copyof(elementData,newCapacity)来实现的。

List子类的区别:

  • ArrayList:
    数组
    线程不安全

    为什么说ArrayList是线程不安全?

    比如多个线程同时 add() ,由于size() 更新不及时的问题,就会出现越界等问题

  • Vector(现在用的少了):
    数组
    线程安全(同时也是有不安全的情况)

    vector之所以是线程安全的,是因为官方在可能涉及到线程不安全的操作都进行了synchronized操作,相当于官方帮你加了一把同步锁。

    那为什么又说他是线程不安全的呢?

    原因很简单,虽然官方帮你加上了同步锁,保证同一时间只会又一个线程操作同一个方法,但是他不能控制多个线程同时操作多个方法,也就是说,删除和添加是可以同时进行的,这就产生一个问题:

    删除实际上是分为两步的,第一步,找到被删除的元素所在下标,第二步,根据下标删除这个元素,而添加也分为两步,第一步,找到添加的下标,第二步,将其设为传入的参数,也就是说存在添加时,找到了数组下标,但是在进行添加时,该数组下标已经被删除的问题。

    ​ 如果是为了保证线程安全,可以使用扩展更好的
    java.util.Collections.SynchronizedList

    或者读多写少的情况下性能比SynchronizedList更好的

    java.util.concurrent.CopyOnWriteArrayList
    java.util.concurrent.CopyOnWriteArraySet

  • LinkedList:
    链表
    线程不安全

  • B:List有三个儿子,我们到底使用谁呢?
    查改多:ArrayList
    增删多:LinkedList
    都多:ArrayList

2.1.2 Set

set和list都是继承自Collection,List可重复,set不可重复,不存在索引所以不能用For遍历

2.2 Map

将键映射到值的对象,<key,value>唯一
Map是双列的,Collection是单列的

V put(K key,V value);//如果key不存在,则返回null,如果已存在,新value覆盖,返回旧key
V remove(K key);//根据key删除对,返回value
void clear();
boolean containsKey(K key);
boolean containsValue(V value);
boolean isEmpty();
V get(K key);
Set keySet();//获取key的set
Collection values();//获取所有value的集合
int size();

2.2.1 HashMap

HashMap的主干是一个Entry数组。Entry是HashMap的基本组成单元,每一个Entry包含一个key-value键值对。(其实所谓Map其实就是保存了两个对象之间的映射关系的一种集合)

线程不安全

//HashMap的主干数组,可以看到就是一个Entry数组,初始值为空数组{},主干数组的长度一定是2的次幂。
//至于为什么这么做,后面会有详细分析。
Entry<K,V>[] table = (Entry<K,V>[]) EMPTY_TABLE;

HashMap采用链地址法(数组+链表)

在这里插入图片描述

LinkedHashMap

底层的数据结构是链表和哈希表,元素有序、唯一

2.2.2 HashTable

HashMap:
(1)由数组+链表组成的,基于哈希表的Map实现,数组是HashMap的主体,
链表则是主要为了解决哈希冲突而存在的。
(2)线程不安全,HashMap可以接受为null的键(key)和值(value)。
(3)HashMap重新计算hash值

Hashtable:
(1)Hashtable 是一个散列表,它存储的内容是键值对(key-value)映射。
(2)Hashtable 的函数都是同步的,这意味着它是线程安全的。它的key、value都不可以为null。
(3)HashTable直接使用对象的hashCode。

clipboard.png

2.2.3 TreeMap集合

key不允许null
TreeMap: 键的数据结构是红黑树,可保证键的排序和唯一性
排序分为自然排序和比较器排序
线程是不安全

posted @ 2021-03-10 23:40  幽灵化石  阅读(130)  评论(0编辑  收藏  举报