数组和集合的特点
1.数组的特点
- 数组一旦被定义长度不可以发生变化
- 数组种的元素有索引
- 数组可以存储基本数据类型和应引用数据类型
- 数组中的元素类型必须一致
数组初始化
动态初始化:数据类型[] 数组名 = new 数组类型[数组长度]
例:int[] arr = new int[5];
静态初始化:数据类型[] 数组名 = new 数组类型[]{元素1,元素2,…}
例:int[] arr = new int[]{1,2,3};
简化格式:数据类型[] 数组名 = {元素1,元素2,…}
例:int[] arr = {1,2,3};
2.集合的特点
- 集合的长度可以发生改变
- 集合只能用于存储引用数据类型(基本数据类型都有相应的包装类)
2.1 单列集合Collection:
- 单列集合类的根接口,用于存储一系列符合某种规则的元素,它有两个重要的子接口,分别是java.util.List和java.util.Set。其中,List的特点是元素有序、元素可重复。Set的特点是元素无序,而且不可重复。List接口的主要实现类有java.util.ArrayList和java.util.LinkedList,Set接口的主要实现类有java.util.HashSet和java.util.TreeSet。
Iterator接口:
- 迭代:即Collection集合元素的通用获取方式。在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来,继续在判断,如果还有就再取出出来。一直把集合中的所有元素全部取出。这种取出方式专业术语称为迭代。
Iterator接口的常用方法如下:
- public E next():返回迭代的下一个元素。
- public boolean hasNext():如果仍有元素可以迭代,则返回 true
增强for
- 增强for循环(也称for each循环)是JDK1.5以后出来的一个高级for循环,专门用来遍历数组和集合的。它的内部原理其实是个Iterator迭代器,所以在遍历的过程中,不能对集合中的元素进行增删操作。
注意
1.数组转换成List之后不能进行add和remove,会报错
String[] array = {"a","b","c"};
List<String> listArray = Arrays.asList(array);
Arrays源码里发现这里new了一个ArrayList的集合,但是这不是ArrayList类,这是Arrays里的一个静态的内部类。此内部类并没有add和remove方法,所以如果此时调用add或者remove方法则会报错。
解决方法:将之前的对象放入一个新的ArrayList对象,再对新的ArrayList对象进行操作
List<String> newStrings = new ArrayList<String>(listArray);
2.HashSet集合存储数据的结构(哈希表)
- 在JDK1.8之前,哈希表底层采用数组+链表实现,即使用链表处理冲突,同一hash值的链表都存储在一个链表里。但是当位于一个桶中的元素较多,即hash值相等的元素较多时,通过key值依次查找的效率较低。
- 而JDK1.8中,哈希表存储采用数组+链表+红黑树实现,当链表长度超过阈值(8)时,将链表转换为红黑树,这样大大减少了查找时间。
Collections
-
java.utils.Collections是集合工具类,用来对集合进行操作。部分方法如下:
-
public static boolean addAll(Collection c, T… elements):往集合中添加一些元素。
-
public static void shuffle(List<?> list) 打乱顺序:打乱集合顺序。
-
public static void sort(List list):将集合中元素按照默认规则排序。
-
public static void sort(List list,Comparator<? super T> ):将集合中元素按照指定规则排序。
说到排序了,简单的说就是两个对象之间比较大小,那么在JAVA中提供了两种比较实现的方式,一种是比较死板的采用java.lang.Comparable接口去实现,一种是灵活的当我需要做排序的时候在去选择的java.util.Comparator接口完成。
- public int compare(String o1, String o2):比较其两个参数的顺序。
两个对象比较的结果有三种:大于,等于,小于。
如果要按照升序排序,
则o1 小于o2,返回(负数),相等返回0,01大于02返回(正数)
如果要按照降序排序
则o1 小于o2,返回(正数),相等返回0,01大于02返回(负数)
//排序方法 按照第一个单词的降序
Collections.sort(list, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o2.charAt(0) - o1.charAt(0);
}
});
2.2 双列集合Map
-
HashMap<K,V>:存储数据采用的哈希表结构,元素的存取顺序不能保证一致。由于要保证键的唯一、不重复,需要重写键的hashCode()方法、equals()方法。
HashMap是非线程安全的,只是用于单线程环境下,多线程环境下可以采用concurrent并发包下的concurrentHashMap。 -
LinkedHashMap<K,V>:HashMap下有个子类LinkedHashMap,存储数据采用的哈希表结构+链表结构。通过链表结构可以保证元素的存取顺序一致;通过哈希表结构可以保证的键的唯一、不重复,需要重写键的hashCode()方法、equals()方法。
-
Hashtable<K,V>:同样是基于哈希表实现的,同样每个元素是一个key-value对,其内部也是通过单链表解决冲突问题,容量不足(超过了阀值)时,同样会自动增长。
HashTable 和 HashMap 的实现原理几乎一样,差别无非是
1.HashTable 不允许 key 和 value 为null;
2.HashTable 是线程安全的。
但是 HashTable 线程安全的策略实现代价却太大了,简单粗暴,get/put 所有相关操作都是 synchronized 的,这相当于给整个哈希表加了一把大锁,多线程访问时候,只要有一个线程访问或操作该对象,那其他线程只能阻塞,相当于将所有的操作串行化,在竞争激烈的并发场景中性能就会非常差。
Propertise类
它是一个双列集合,它的键值对都是String类型
常用方法
- Object setProperty(String key, String value)
添加/修改,键和值 - String getProperty(String key)
根据键获取值 - void load(InputStream inStream)
把文件中的键值对,读取到Propertise中,文件中键值对的格式必须是key=value - void store(OutputStream out, String comment)
把propertise集合中的键值对保存到文件中,参数comment为写入的注释