java 数组,集合,字符串中常用的方法
数组Arrays 类
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import java.util.Arrays;
Arrays.toString()
Arrays.sort()
Arrays.equals()
Arrays.binarySearch( c数组,key定值)
Arrays.copyOf()
Arrays.copyOfRange(arr,from A,to B)
|
字符串String类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| int length(); char charAt(); char toCharArray(); String trim(); String toUpperCase(); String toLowerCase(); boolean isEmptyt(); boolean equalsIgnoreCase(String s); int compareTo(String s); String substring(int beginIndex); String subString(int begin ,int end); boolean contains(String str); int indexOf(String str) indexOf(String str,int index); String replace(char oldChar,newChar); boolean matches(String str); String [] split("字符");
|
1 2 3 4 5 6 7 8 9 10 11 12
| StringBuffer 线程安全: StringBuffer 是线程安全的,因此适用于多线程环境,可以确保在并发操作时不会出现数据不一致的问题。 同步方法: StringBuffer 的方法都是同步的,这会带来一些性能上的损失。因此,当需要在线程安全的环境中进行字符串操作时,使用 StringBuffer 是合适的选择。
StringBuilder JDK1.5版本之后引入的 非线程安全: StringBuilder 不是线程安全的,因此在单线程环境中使用更为高效。
性能优势: 由于不需要考虑线程安全性,StringBuilder 在性能上通常比 StringBuffer 更优秀。在单线程环境中进行大量字符串操作时,使用 StringBuilder 可以提高效率。
选择场景: 多线程环境: 如果在多线程环境中需要进行字符串操作,选择 StringBuffer。 单线程环境: 如果在单线程环境中进行字符串操作,选择 StringBuilder 可以获得更好的性能。
|
StringBuilder的常用方法
1 2 3 4 5 6 7 8 9 10 11 12
| StringBuilder str = new StringBuilder("helloworld"); (int capacity); (空参构造器) str.append(String str); str.delete(int start,int end); deletecharAt(int index); str.replace(int start,int end,String str); str.insert(int start,String s); str.reverse(); public int indexOf(String str) public String substring(int start,int end) public void setCharAt(int n,char ch)
|
集合框架:collection接口继承树
集合框架:
Collection接口:单列集合,用来存储一个一个的对象
list接口:存储有序的,可以重复的数据 –>”动态数组”
ArrayList: list的主要实现类,线程不安全。底层使用object[]数组存储
LinkedList:底层使用双向链表存储。对于频繁的插入和删除操作,效率高
Vector:古老实现类,线程安全,效率低
set接口:无序的,不可重复的数据 –>高中数学中的集合
1 2 3
| 无序性,不等于随机性,存储数据根据数据计算哈希值,根据哈希值存储
不可重复性:靠存储的元素类型是否重写hashcode()和equals()方法实现的,比较过程:存储元素会使用hash()算法生成一个int类型的hashcode散列值,然后与以存储的元素的hashcode比较,如果不一致则是新的对象,如果一致的话,再调用equals()方法,比较两个对象的内容是否相等,这样就确保了存储的唯一性。
|
HashSet:set接口的主要实现类,线程不安全,可以存储null值,底层使用哈希表
LinkedHashSet:HashSet的子类,可以按照添加的顺序遍历,底层使用哈希表和链表,频繁遍历效率高
TreeSet:底层二叉树红黑树,可以按照添加的对象的指定属性,排序,所以只能添加同类的对象
TreeSet底层数据结构采用二叉树来实现,元素唯一且已经排好序;唯一性同样需要重写hashCode和equals()方法,二叉树结构保证了元素的有序性。根据构造方法不同,分为自然排序(无参构造)和比较器排序(有参构造),自然排序要求元素必须实现Compareable接口,并重写里面的compareTo()方法,元素通过比较返回的int值来判断排序序列,返回0说明两个对象相同,不需要存储;比较器排需要在TreeSet初始化是时候传入一个实现Comparator接口的比较器对象,或者采用匿名内部类的方式new一个Comparator对象,重写里面的compare()方法;

Map接口:双列集合,用来存储一对(key,value)的数据 ,底层数组+链表+红黑树
HashMap:主要实现类。线程不安全,效率高,可以存储null,
LinkedHashMap:底层链表,保证在遍历元素时候,可以按照添加的顺序遍历,频繁的遍历效率高
WeakHashMap:
Hashtable:古老实现类。线程安全,效率低,不能存储null
properties:常用来处理配置文件,key-value都是String类型的
TreeMap:底层红黑树,保证添加的key进行排序(key必须是同一类对象)实现排序遍历
map中的key:无序的,不可重复的,使用set存储所有的key
value:无序的,可重复的
map的底层实现原理:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| JDK8之后map底层是 数组+链表+红黑树 当首次执行执行插入操作map.put(key,value)后,底层创建一个长度为16的数组 key相当于set不可重复,调用key1类所在的hashcode()计算哈希值,不一样,根据hash值计算出存储在数组中的位置, 若存放位置为空的话,则添加成功 若存放位置的数据不为空,(说明此位置已经有一个或者多个数据了,以链表的形式存在),比较key1和已有元素的hash值,如果都不相同,则添加成功, 如果相同,则继续比较key1类所在的equals()方法,判断是否为相同的元素, 如果不相同,则直接添加 如果相同,则使用新的的value值,替换之前的value值
当使用hashcode()计算出的数组的一个索引位置上的元素以链表的形式存在的结构个数>8,并且当前数组的长度大于16的时候,此时将此索引位置上所有的数据改为使用红黑树存储,为了提高查找的效率
再不断的添加数据的过程中,会涉及到底层数组扩容的问题
HashMap 的底层数组在什么时候扩容,是由负载因子(Load Factor)和阈值(Threshold)决定的。负载因子是一个表示哈希表满程度的值,而阈值则是根据负载因子和数组长度计算得出的阈值。当哈希表中的元素个数超过阈值时,数组会进行扩容操作。默认扩容为原来的2倍
具体来说,扩容的触发条件是:元素个数超过阈值。而阈值的计算方式为:threshold=capacity×loadFactor 其中: capacity 是哈希表数组的容量(数组的长度)。 loadFactor 是负载因子,默认为 0.75。 当哈希表中的元素个数达到阈值时,就会触发数组的扩容。扩容的具体过程包括:
创建新数组: 创建一个新的数组,其容量是原数组的两倍。 重新哈希: 将原数组中的所有元素重新计算哈希码,并放入新数组中。由于数组容量变化,哈希码的计算可能会得到不同的索引位置。 替换原数组: 将新数组替换为原数组。
|
map的主要方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| void clear(): boolean containsKey(Object key) boolean containsValue(Object value)
Object get(Object key) boolean isEmpty() Object put(key,value); void putAll(); Object remove(key); int size(); int getOrDefault(key, defaultValue)
Set entrySet() Set keySet() Collection values();
|
HashMap中按照key和value排序的两种方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
|
Set set = map.keyset(); Object[] arr = set.toArray(); for(Object key :arr){ map.get(key); }
List<Map.Entry<String, Integer>> list = new ArrayList(map.entrySet());
list.sort(new Comparator<Map.Entry<String, Integer>>() { @Override public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) { return o2.getValue().compareTo(o1.getValue()); } });
Collections.sort(list, new Comparator<Map.Entry<String, Integer>>() { @Override public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) { return o2.getValue().compareTo(o1.getValue()); } });
|

集合和数组
长度区别:数组固定,集合长度可变
内容区别:数组可以是基本的数据类型,也可以是引用的数据类型
集合只能是引用类型
元素内容:数组只能存储同一种类型
集合可以存储不同类型的(一般也是同一种类型的)
collection集合的方法:
1 2 3 4 5 6 7 8 9 10
| boolean add(E e); boolean remove(Object o); void clear(); boolean contains(O o); boolean isEmpty(); int size(); boolean addAll(Collection c); Object[] toArray(); Iterator iterator(); iterator.next(),iterator.hasnext()
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| collection和collections的区别 collection是所有集合的接口,list,set,map collections是操作集合的工具类;
collections的常用方法,都是静态方法,static,直接调用它 Collections.reverse(list); shuffle(list); sort(); sort(list,comparator); swap(list,int i,int j); max(); min(); frequency(Collection,Object o); copy(list dest,list,src); replaceAll(list,old,new); Collections提供了多个synchronizedXxx()方法,解决ArrayList,Hashmap等线程安全的问题
|
List集合

总结:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| 增:add(Object)
删:remove(int index)/remove(Object obj)
改:set(int index,Object o)
查:get(int index)
长度:size()
遍历:foreach 迭代器Iterator()
集合-->数组:toArray() 数组-->集合:Arrays.asList();
|
1.基本概念
java与C、C++的异同
1.相同,java和C++都是面向对象的语言,封装,继承,多态
封装:就是将对象的属性和状态封装在一个类中,并且提供公共的public来get,set此属性的值。好处是,高内聚,低耦合,隐藏对象内部的复杂性,只对外公开简单的接口,供外界调用
继承:extends,子类可以继承父类的属性和方法,不修改父类的情况下添加自己的新成员方法,子类成员通过super关键字调用父类的构造方法和成员。
多态性质:同一操作对不同的对象,有不同的解释,就是多态性(父类的引用指向子类的对象)
通过方法重写override或者方法重载
2.不同之处:
java是解释性的语言,运行过程为:java编译后生成字节码文件,然后在java虚拟机JVM中解释运行,
C++编译型语言,编译后直接生成二进制的字节码文件,所以C++运行速度快,但是java可以移植
java中没有指针,提供了数组和集合这样的类和方法去操作,使得程序更加安全
java中没法实现多重继承,只能实现多个接口来达到与C++中多重继承的作用
C++中,经常需要去malloc去分配和释放内存,java中有垃圾回收机制,会自动释放内存
C++支持运算符的重载,java不支持
C++更接近底层,允许更多的底层控制,java隐藏了更多的底层细节,提供了丰富的库和内置功能
1 2 3 4
| 集合collection中存储的如果是自定义的对象,需要重写哪儿些方法 list:equals()方法判断对象的属性是否相等 hashset:重写equals()和hashcode()方法,为什么要重写hashcode,这与hashset的比较过程是有关系的,存储对象会采用hash算法生成一个int类型的哈希值,如果hash值不一样判断不是相同的元素,再存储,如果hash值一样,就调用equals 方法判断,所以不去重写的话,会调用父类的hash算法,这样相同的元素就会被判断为不同的hash值,就违背了set表不能有重复元素的定义 treeset:底层二叉树,元素唯一且已经排好序,因为需要排序,所以就需要在compare方法里定义比较对象的属性,进行排序。重写compareTo(),compare()
|
线程安全和线程不安全
1 2 3
| 线程安全就是:多线程访问时候,提供一种加锁的机制,当其中一个线程访问的时候,其他的线程不能进行访问,从而达到保护数据的目的,对java中的synchronized关键字 线程不安全:不加锁,有可能出现多个线程先后更爱数据得到的是错误数据 例如:1000张票,A和B同时买票,如果线程不安全,会出现同时执行1000-1 的操作,导致最后剩下999张票,而不是998张
|
例题:理解hashset的底层
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| HashSet hashSet = new HashSet(); Person p1 = new Person("A", 1); Person p2 = new Person("B", 2); hashSet.add(p1); hashSet.add(p2); System.out.println(hashSet);
p1.age = 3; hashSet.remove(p1); System.out.println(hashSet);
hashSet.add(new Person("A",3)); System.out.println(hashSet);
hashSet.add(new Person("A",1)); System.out.println(hashSet);
输出: [Person{name='A', age=1}, Person{name='B', age=2}] [Person{name='A', age=3}, Person{name='B', age=2}] [Person{name='A', age=3}, Person{name='B', age=2}, Person{name='A', age=3}] [Person{name='A', age=3}, Person{name='B', age=2}, Person{name='A', age=1}, Person{name='A', age=3}] 解析:先往set添加了两个元素,所以输出两个
|
栈和队列
栈
1 2 3 4 5 6 7 8 9
| Stack<Integer> ans = new Stack<>();
push(value) pop() peek() isEmpty() size() search(Object o)
|
队列
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
Queue<Integer> queue = new LinkedList<Integer>();
add(E e):将元素 e 插入到队列末尾,如果插入成功,则返回 true;如果插入失败(即队列已满),则会抛出异常;
remove():移除队首元素,若移除成功,则返回 true;如果移除失败(队列为空),则会抛出异常;
remove(Object o):移除指定的元素,若移除成功,则返回 true;如果移除失败(队列为空),则会抛出异常
offer(E e):将元素 e 插入到队列末尾,如果插入成功,则返回 true;如果插入失败(即队列已满),则返回 false;
poll():移除并获取队首元素,若成功,则返回队首元素;否则返回 null;
peek():获取队首元素,若成功,则返回队首元素;否则返回 null
isEmpty():队列是否为空
size():队列长度
对于非阻塞队列,一般情况下建议使用 offer、poll 和 peek 三个方法,不建议使用 add 和 remove 方法。因为使用 offer、poll 和 peek 三个方法可以通过返回值判断操作成功与否,而使用 add 和 remove 方法却不能达到这样的效果。
|