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数组来进行改变字符内容
//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倍增长(部分集合底层也是用数组来做的)
- 区别1 :
-
C:数组和集合什么时候用
* 如果元素个数是固定的推荐用数组
* 如果元素个数不是固定的推荐用集合
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);
-
LinkedList
void addFirst(E e); void addLast(E e); E getFirst(); E getLast(); E removeFirst(); E removeLast();
-
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。
2.2.3 TreeMap集合
key不允许null
TreeMap: 键的数据结构是红黑树,可保证键的排序和唯一性
排序分为自然排序和比较器排序
线程是不安全