文章目录
- 集合
-
- 集合结构图
- 集合概念
-
- Collection
- Collection接口常用方法
- List
-
- ArrayList类
-
- 特点
- Vector
- LinkedList类
- List特点
-
- 创建List
- 遍历List
- List和Array转换
- Set
-
- HashSet
- TreeSet
- Map
-
- Map常用的方法
- HashMap
- TreeMap
- 常用类
-
- Object类
-
- 类中方法
- String类
-
- 创建字符串
- 字符串比较
- 字符串长度
- 连接字符串
- 操作子串
- 字符串方法
- StringBuilder和StringBuffer类
-
- StringBuffer方法
- System类
-
- arraycopy()方法
- currentTimeMillis()方法
- gc()方法
- exit(int status)方法
- Date日期类
-
- 基本概念
- Date
- LocalDateTime
- ZonedDateTime
- DateTimeFormatter
- 日期时间字符串转换
集合
集合结构图
集合概念
-
以便于处理一组类似的数据,例如:
- 计算所有学生的总分和平均分
- 列出所有商品名称和价格
在Java如果一个对象能在内部持有几个其他对象Java对象,并提供界提供访问接口,该对象成为集合。数组可视为集合
//可持有10个String对象 String[] string = new String[10]; //可以放入String对象 string[0] = "hello"; //获取String对象 String hello = string[0];
- 数组初始化后,小不变
- 数组只能按索引顺序存取
因此,不同类型的集合类需要处理不同的数据,例如:
- 可变大小的顺序链表
- 确保无重复元素的集合
- …
Collection
-
Java自带标准库java.util包提供集合类:Collection,它是除Map其他类型的外部根接口。java.util包下主要提供三种类型的集合:
- List:一种例如,列表的集合按索引排列Student的List;
- Set:一种保证例如,所有无重复名称的元素集合Student的List;
- Map:一种通过例如,根据Student的name查找对象Student的Map。
-
Java集合接口的特点:
-
例如,有序表的接口是实现接口与实现类的分离List,具体实现类有ArrayList,LinkedList等
-
支持泛型,只能在一个集合中放置相同类型的元素,例如:
List<String> list = new ArrayList<>();//只能放String类型
-
-
Java访问集合总是通过统一的方式:迭代器(Iterator)来实现,好处在于无需知道集合内部元素是按什么方式存储的。
-
不应该继续使用的遗留类:
- Hashtable:一种线程安全的Map实现
- Vector:一种线程安全的List实现
- Stack:基于Vector实现的LIFO的栈
-
不该使用的遗留接口:
- Enumberation:已被Iterator< E >取代
Collection接口常用方法
方法名称 | 说明 |
---|---|
boolean add(E e) | 向集合中添加一个元素,如果集合对象被添加操作改变了,则返回 true。E 是元素的数据类型 |
boolean addAll(Collection c) | 向集合中添加集合 c 中的所有元素,如果集合对象被添加操作改变了,则返回 true。 |
void clear() | 清除集合中的所有元素,将集合长度变为 0。 |
boolean contains(Object o) | 判断集合中是否存在指定元素 |
boolean containsAll(Collection c) | 判断集合中是否包含集合 c 中的所有元素 |
boolean isEmpty() | 判断集合是否为空,是空则返回true |
Iteratoriterator() | 返回一个 Iterator 对象,用于遍历集合中的元素 |
boolean remove(Object o) | 从集合中删除一个指定元素,当集合中包含了一个或多个元素 o 时,该方法只删除第一个符合条件的元素,该方法将返回 true。 |
boolean removeAll(Collection c) | 从集合中删除所有在集合 c 中出现的元素(相当于把调用该方法的集合减去集合 c)。如果该操作改变了调用该方法的集合,则该方法返回 true。 |
boolean retainAll(Collection c) | 从集合中删除集合 c 里不包含的元素(相当于把调用该方法的集合变成该集合和集合 c 的交集),如果该操作改变了调用该方法的集合,则该方法返回 true。 |
int size() | 返回集合中元素的个数 |
Object[] toArray() | 把集合转换为一个数组,所有的集合元素变成对应的数组元素。 |
List
- 也是一个顶层接口,它继承了Collection接口,同时也是ArrayList、LinkedList等集合元素的父类
- 在集合类中,List是一种有序列表,List行为几乎与数组相同,List内部按照放入元素的先后顺序存放,每个元素可以通过索引确定自己的位置,List的索引和数组一样从0开始。
ArrayList类
ArrayList是实现了List接口的**可扩容数组(动态数组)
**,他的内部是基于数组实现的,具体定义如下:
public class ArrayList<E> extends AbstractList<E> implements List<E>,
RandomAccess,Cloneable,java.io.Serializable {
...}
- ArrayList可以实现所有可选择的列表操作,允许所有的元素,包括空值。ArrayList还提供了内部存储Iist的方法,它能够完全替代Vector,只有一点例外,ArrayList不是
- ArrayList有一个容量的概念,这个数组的容量就是List用来存储元素的容量。
- ArrayList不是线程安全的容器,如果多个线程中至少有两个线程修改了ArrayList的结构的话就会导致线程安全问题,作为替代条件可以使用线程安全的List,应使用
Collections.synchronizedList
List list = Collections.synchronizedList(new Array(...));
- ArrayList具有fail-fast快速失败机制,能够对ArrayList作出失败检测。当迭代集合的过程中该集合在结构上发生改变的时候,就有可能,会发生fail-fast,即抛出
ConcurrentModificationException
异常
特点
- ArrayList实现了可变数组的大小,存储在内的数据成为元素,提供了的方式,对支持较好。
- 使用 ArrayList 创建的集合,允许对集合中的元素进行快速的随机访问,不过,向 ArrayList 中
- ArrayList 类的常用构造方法有如下两种重载形式:
- ArrayList():构造一个初始容量为 10 的空列表。
- ArrayList(Collection<? extends E> c):构造一个包含指定 Collection 元素的列表,这些元素是按照该 Collection 的迭代器返回它们的顺序排列的。
ArrayList arrayList = new ArrayList();
ArrayList temp = new ArrayList(arrayList);
- ArrayList类除包含Collection接口中的方法之外,还包括List接口中提供的方法:
方法名称 | 说明 |
---|---|
E get(int index) | 获取此集合中指定索引位置的元素,E 为集合中元素的数据类型 |
int index(Object o) | 返回此集合中第一次出现指定元素的索引,如果此集合不包含该元 素,则返回 -1 |
int lastIndexOf(Object o) | 返回此集合中最后一次出现指定元素的索引,如果此集合不包含该 元素,则返回 -1 |
E set(int index, Eelement) | 将此集合中指定索引位置的元素修改为 element 参数指定的对象。 此方法返回此集合中指定索引位置的原元素 |
List subList(int fromlndex, int tolndex) | 返回一个新的集合,新集合中包含 fromlndex 和 tolndex 索引之间的所有元素。包含 fromlndex 处的元素,不包含 tolndex 索引处的元素 |
public class ArrayList_1 {
public static void main(String[] args) {
@SuppressWarnings({
"all"})
ArrayList arrayList = new ArrayList();
//允许重复元素,允许添加null
arrayList.add("12");
arrayList.add("12");
arrayList.add("zcz");
arrayList.add(null);
//[12, 12, zcz, null]
System.out.println(arrayList);
//get(int index)获取元素
String a = (String)arrayList.get(0);//12
System.out.println(a);
//返回一次出现12的索引
System.out.println(arrayList.indexOf("12"));//0
//set修改指定索引位置的元素,返回原元素
arrayList.set(1,10);
System.out.println(arrayList);//[12, 10, zcz, null]
//返回新集合,包含arrayList中0~2索引的元素
List list = arrayList.subList(0,2);
System.out.println(list);//[12, 10]
}
}
Vector
- Vector同ArrayList一样,都是基于数组实现的,只不过Vector是一个线程安全的容器,它对内部的每个方法都简单粗暴的上锁,避免多线程引起的安全性问题,但是通常这种同步方式需要的开销比较大,因此,访问元素的效率要远远低于ArrayList。
- 还有一点在于扩容上,ArrayList扩容后的数组长度会增加50%,而Vector的扩容长度后数组会增加一倍。
LinkedList类
LinkedList是一个双向链表,允许存储任何元素(包括nul)。它的主要特性如下:
- LinkedList所有的操作都可以表现为的,索引到链表的操作将遍历从头到尾,视哪个距离近为遍历顺序。
- ·注意这个实现也的,如果多个线程并发访问链表,并且至少其中的一个线程修改了链表的结构,那么这个链表必须进行外部加锁。或者使用
List list = Collections.synchronizedList(new LinkedList(...));
- LinkedList 类采用链表结构保存对象,这种结构的优点是便于向集合中插入或者删除元素。需要频繁向集合中插入和删除元素时,使用 LinkedList 类比 ArrayList 类效果高,但是 LinkedList 类随机访问元素的速度则相对较慢。这里的随机访问是指检索集合中特定索引位置的元素。
- LinkedList除Collection和List接口外的方法
方法名称 | 说明 |
---|---|
void addFirst(E e) | 将指定元素添加到此集合的开头 |
void addLast(E e) | 将指定元素添加到此集合的末尾 |
E getFirst() | 返回此集合的第一个元素 |
E getLast() | 返回此集合的最后一个元素 |
E removeFirst() | 删除此集合中的第一个元素 |
E removeLast() | 删除此集合中的最后一个元素 |
public class LinkedList_ {
public static void main(String[] args) {
Person wang = new Person("wang",23);
Person zhang = new Person("zhang",20);
Person yao = new Person("yao",48);
LinkedList linkedList = new LinkedList();
linkedList.add(wang);
linkedList.add(zhang);
linkedList.add(yao);
//添加对象到LinkedList集合中,toString方法输入对象信息
System.out.println(linkedList);
//添加元素到集合开头
Person li = new Person("li",12);
linkedList.addFirst(li);
//添加元素到集合末尾
Person zhao = new Person("zhao",19);
linkedList.addLast(zhao);
//返回集合第一个与最后一个元素
System.out.println(linkedList.getFirst());
System.out.println(linkedList.getLast());
//删除集合中第一个或最后一个元素并返回
System.out.println(linkedList.removeFirst());
System.out.println(linkedList.removeLast());
}
}
List特点
- 使用
List
时,我们要关注List
接口的规范。List
接口允许我们添加重复的元素,即List
内部的元素可以重复 - 允许添加null
创建List
除了使用ArrayList
和LinkedList
,我们还可以通过List
接口提供的of()
方法,根据给定元素快速创建List
List<Integer> list = List.of(1,2,3);
但是List.of()
方法不接受null
值,如果传入null
,会抛出NullPointerException
异常。
遍历List
- 和数组类型相同,遍历一个
List
,可以用for
循环根据索引配合get(int)
方法遍历:
public class Main {
public static void main(String[] args) {
List<String> list = List.of("apple", "pear", "banana");
for (int i=0; i<list.size(); i++) {
String s = list.get(i);
System.out.println(s);
}
}
}
- 通过迭代器
Iterator
来遍历List
。通过Iterator
遍历List
是最高效的方式。
public class Main {
public static void main(String[] args) {
List<String> list = List.of("apple", "pear", "banana");
//List实例调用iterator()创建Iterator对象
//boolean hasNext()判断是否有下一个元素
//E next()返回下一个元素
for (Iterator<String> it = list.iterator(); it.hasNext(); ) {
String s = it.next();
System.out.println(s);
}
}
}
- for-each循环遍历集合
public class Main {
public static void main(String[] args) {
List<String> list = List.of("apple", "pear", "banana");
for (String s : list) {
System.out.println(s);
}
}
}
List和Array转换
- 把
List
变为Array
有三种方法,第一种是调用toArray()
方法直接返回一个Object[]
数组:
public class Main {
public static void main(String[] args) {
List<String> list = List.of("apple", "pear", "banana");
//以正确顺序返回一个包含此列表中所有元素的数组
//此方法容易丢失类型信息,应用较少
Object[] array = list.toArray();
for (Object s : array) {
System.out.println(s);
}
}
}
- 第二种方式是给
toArray(T[])
传入一个类型相同的Array
,List
内部自动把元素复制到传入的Array
中:
public class Main {
public static void main(String[] args) {
List<Integer> list = List.of(12, 34, 56);
Integer[] array = list.toArray(new Integer[3]);
for (Integer n : array) {
System.out.println(n);
}
}
}
- 注意到这个
toArray(T[])
方法的泛型参数<T>
并不是List
接口定义的泛型参数<E>
,所以,我们实际上可以传入其他类型的数组,例如我们传入Number
类型的数组,返回的仍然是Number
类型:
public class Main {
public static void main(String[] args) {
List<Integer> list = List.of(12, 34, 56);
Number[] array = list.toArray(new Number[3]);
for (Number n : array) {
System.out.println(n);
}
}
}
Integer[] array = list.toArray(new Integer[list.size()]);
Set
- Set 集合类似于一个罐子,程序可以依次把多个对象“丢进”Set 集合,而 Set 集合通常不能记住元素的添加顺序。也就是说 Set 集合中的对象不按特定的方式排序,只是简单地把对象加入集合。Set 集合中,并且最多只允许包含一个 null 元素。
- Set 实现了 Collection 接口,它主要有两个常用的实现类:HashSet 类和 TreeSet类。
HashSet
- ,大多数时候使用 Set 集合时就是使用这个实现类。HashSet 是按照 Hash 算法来存储集合中的元素。因此具有很好的
- HashSet 特点:
- 不能保证元素的排列顺序,顺序可能与添加顺序不同,顺序也有可能发生变化。
- HashSet 不是同步的,如果多个线程同时访问或修改一个 HashSet,则必须通过代码来保证其同步。
- 集合元素值可以是 null。
- 当向 HashSet 集合中存入一个元素时,HashSet 会调用该对象的 hashCode() 方法来得到该对象的 hashCode 值,然后根据该 hashCode 值决定该对象在 HashSet 中的存储位置。**如果有两个元素通过 equals() 方法比较返回的结果为 true,但它们的 hashCode 不相等,**HashSet 将会把它们存储在不同的位置,依然可以添加成功。
- 只有两个对象的 hashCode 值相等且通过 equals() 方法比较返回结果为 true,HashSet 集合才认为两个元素相等。
//创建HashSet对象
HashSet hs = new HashSet(); // 调用无参的构造函数创建HashSet对象
HashSet<String> hss = new HashSet<String>(); // 创建泛型的 HashSet 集合对象
TreeSet
- **TreeSet 类同时实现了 Set 接口和 SortedSet 接口。SortedSet 接口是 Set 接口的子接口,可以实现对集合进行自然排序,**因此使用 TreeSet 类实现的 Set 接口默认情况下是自然排序的,这里的自然排序指的是升序排序。
- **TreeSet 只能对实现了 Comparable 接口的类对象进行排序,**因为 Comparable 接口中有一个 compareTo(Object o) 方法用于比较两个对象的大小。例如 a.compareTo(b),如果 a 和 b 相等,则该方法返回 0;如果 a 大于 b,则该方法返回大于 0 的值;如果 a 小于 b,则该方法返回小于 0 的值。
类 | 比较方式 |
---|---|
包装类(BigDecimal、Biglnteger、 Byte、Double、 Float、Integer、Long 及 Short) | 按数字大小比较 |
Character | 按字符的 Unicode 值的数字大小比较 |
String | 按字符串中字符的 Unicode 值的数字大小比较 |
- TreeSet 类除 Collection 接口之外的方法
方法名称 | 说明 |
---|---|
E first() | 返回此集合中的第一个元素。其中,E 表示集合中元素的数据类型 |
E last() | 返回此集合中的最后一个元素 |
E poolFirst() | 获取并移除此集合中的第一个元素 |
E poolLast() | 获取并移除此集合中的最后一个元素 |
SortedSet subSet(E fromElement,E toElement) | 返回一个新的集合,新集合包含原集合中 fromElement 对象与 toElement 对象之间的所有对象。包含 fromElement 对象,不包含 toElement 对象 |
SortedSet headSet(E toElement) | 返回一个新的集合,新集合包含原集合中 toElement 对象之前的所有对象。 不包含 toElement 对象 |
SortedSet tailSet(E fromElement) | 返回一个新的集合,新集合包含原集合中 fromElement 对象之后的所有对 象。包含 fromElement 对象 |
Map
- Map 是一种键-值对(key-value)集合,Map 集合中的每一个元素都包含一个键(key)对象和一个值(value)对象。用于保存具有映射关系的数据。
- Map 接口主要有两个实现类:。其中,
Map中的常用方法
方法名称 | 说明 |
---|---|
void clear() | 删除该 Map 对象中的所有 key-value 对。 |
boolean containsKey(Object key) | 查询 Map 中是否包含指定的 key,如果包含则返回 true。 |
boolean containsValue(Object value) | 查询 Map 中是否包含一个或多个 value,如果包含则返回 true。 |
V get(Object key) | 返回 Map 集合中指定键对象所对应的值。V 表示值的数据类型 |
V put(K key, V value) | 向 Map 集合中添加键-值对,如果当前 Map 中已有一个与该 key 相等的 key-value 对,则新的 key-value 对会覆盖原来的 key-value 对。 |
void putAll(Map m) | 将指定 Map 中的 key-value 对复制到本 Map 中。 |
V remove(Object key) | 从 Map 集合中删除 key 对应的键-值对,返回 key 对应的 value,如果该 key 不存在,则返回 null |
boolean remove(Object key, Object value) | 删除指定 key、value 所对应的 key-value 对。如果从该 Map 中成功地删除该 key-value 对,该方法返回 true,否则返回 false。 |
Set entrySet() | 返回 Map 集合中所有键-值对的 Set 集合,此 Set 集合中元素的数据类型为 Map.Entry |
Set keySet() | 返回 Map 集合中所有键对象的 Set 集合 |
boolean isEmpty() | 查询该 Map 是否为空(即不包含任何 key-value 对),如果为空则返回 true。 |
int size() | 返回该 Map 里 key-value 对的个数 |
Collection values() | 返回该 Map 里所有 value 组成的 Collection |
HashMap
HashMap是一个利用哈希表原理来存储元素的集合,并且允许空的key-value键值对。HashMap是非线程安全的,也就是说在多线程的环境下,可能会存在问题,而Hashtable是线程安全的容器。HashMap也支持fai-fast机制。HashMap的实例有两个参数影响其性能:**初始容量和加载因子。**可以使用Collections.synchronizedMap(new HashMap(..))
来构造一个线程安全HashMap。
public class Map_a { public static void main(String[] args) { HashMap user = new HashMap(); user.put("1","zhang"); user.put("2","wang"); user.put("3","liu"); System.out.println(user); //删除键值为3的元素,返回value user.remove("3"); System.out.println(user); //根据键返回返回指定对象的值 System.out.println 标签:
02重载连接器he