集合
一、概述
- 集合、数组都是对多个数据进行存储操作的结构,简称Java容器
- 说明:此时的存储,主要指的是内存层面的存储,不涉及到持久化的存储(.txt,.jpg,数据库中)
二、集合框架
2.1 Collection接口
- 概述:单列集合,用来存储对象
- 结构:
- List接口
- Set接口
2.1.1 List接口
- 概述:存储有序的、可重复的数据
- 实现类:
- ArrayList类:作为List接口的主要实现类,线程不安全的,效率高,底层使用Object[]数组存储
- LinkedList类:对于频繁插入、删除操作,使用此类效率比ArrayList高,底层使用双向链表存储
- Vector类:作为List接口的古老实现类,效率高;底层使用Object[]数组存储
- 相同点:三个类都实现了List接口,存储数据特点相同
- ArrayList简单代码练习
public class ListTest {
@Test
public void test(){
ArrayList list =new ArrayList();
list.add(123);
list.add(456);
list.add("AA");
list.add(new Person("wang",18));
list.add(456);
//链表长度
System.out.println(list.size());
//删除指定索引处的元素
System.out.println(list.remove(1));
System.out.println(list.size());
System.out.println(list);
list.add(1,"YSW");
System.out.println(list);
//得到指定索引处的元素
System.out.println(list.get(1));
System.out.println("-----------------------------------------------------");
//在指定所引出添加元素
list.add(1,456);
//返回第一次出现元素value时的索引
System.out.println(list.indexOf(456));
//返回最后出现元素value时的索引
System.out.println(list.lastIndexOf(456));
System.out.println(list);
Object set = list.set(0, 1);
System.out.println(set);
System.out.println(list);
List list1 = list.subList(3, 6);
System.out.println(list1);
System.out.println("-----------------------------------------------------");
//通过迭代器遍历输出元素
Iterator iterator = list.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
}
}
- Iterator迭代器接口练习
public class IteratorTest {
@Test
public void test1() {
Collection coll = new ArrayList();
coll.add(123);
coll.add("abc");
coll.add(456);
coll.add(false);
Iterator iterator = coll.iterator();
//方法一:
// System.out.println(iterator.next());
// System.out.println(iterator.next());
// System.out.println(iterator.next());
// System.out.println(iterator.next());
// //报异常:java.util.NoSuchElementException
// System.out.println(iterator.next());
//方法二:不推荐
// for (int i = 0; i <coll.size() ; i++) {
// System.out.println(iterator.next());
// }
//方法三:推荐
while(iterator.hasNext()){
System.out.println(iterator.next());
}
}
@Test
public void test2(){
Collection coll = new ArrayList();
coll.add(123);
coll.add("abc");
coll.add(456);
coll.add(false);
coll.add("Tom");
Iterator iterator = coll.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
System.out.println("------------------------------------");
Iterator iterator1 = coll.iterator();
while(iterator1.hasNext()){
Object obj=iterator1.next();
if("Tom".equals(obj)){
//移除集合中的元素
iterator1.remove();
//iterator1.remove(); 调用remove之后再调remove会报:java.lang.IllegalStateException
}
}
Iterator iterator2 = coll.iterator();
while(iterator2.hasNext()){
System.out.println(iterator2.next());
}
}
}
- 常用方法练习
public class List {
@Test
public void test(){
Collection coll =new ArrayList();
//add():
coll.add("AA");
coll.add("BB");
coll.add(123);//自动装箱
coll.add("Tom");
coll.add(new Date());
coll.add(new Person("Ysw",18));
//size():
//获取元素个数
// System.out.println(coll.size());
Collection coll1=new ArrayList();
coll1.add("EE");
coll1.add(345);
//addAll(coll1):将coll1集合中的元素添加到当前的集合中
coll.addAll(coll1);
// System.out.println(coll.size());
// System.out.println(coll);
//isEmpty():判断当前集合是否为空
// System.out.println(coll.isEmpty());
// //clear():清空集合元素
// coll.clear();
// System.out.println(coll.isEmpty());
boolean contains=coll.contains(123);
System.out.println(contains);
System.out.println(coll.contains("Tom"));
//Collection接口的实现类的对象中添加数据obj时,要求obj所在类要重写equals()。
System.out.println(coll.contains(new Person("Ysw",18)));
System.out.println("--------------------------------------------");
//containsAll(Collection coll1):判断形参coll1中的所有元素是否都存在于当前集合当中
System.out.println(coll.containsAll(coll1));
Collection coll2=Arrays.asList(123,3456);
System.out.println(coll.containsAll(coll2));
}
@Test
public void test2(){
Collection coll =new ArrayList();
coll.add("AA");
coll.add("BB");
coll.add(123);//自动装箱
coll.add(456);
coll.add("Tom");
coll.add(new Date());
coll.add(new Person("Ysw",18));
//remove(Object obj):
System.out.println(coll);
coll.remove("AA");
coll.remove(new Person("Ysw",18));
System.out.println(coll);
Collection coll2=Arrays.asList(123,456,78);
//removeAll(Collection coll2):从前集合当中移除college中所有元素
// System.out.println(coll);
// coll.removeAll(coll2);
// System.out.println(coll);
//retainAll(Collection coll2):交集:获取当前集合和coll集合的交集,并且返回给当前集合
coll.retainAll(coll2);
System.out.println(coll);
System.out.println("----------------------------------------");
//equals(Object obj):判断当前集合和形参集合元素是否相同;
Collection coll3=Arrays.asList(123,456,78);
System.out.println(coll2.equals(coll3));
//hashCode():返回当前对象的哈希值
System.out.println(coll.hashCode());
System.out.println("----------------------------------------");
//集合转换为数组 toArray()
Object[] arr = coll3.toArray();
for (int i = 0; i <arr.length ; i++) {
System.out.println(arr[i]);
}
//iterator():返回Iterator接口的实例,用于遍历集合元素。
}
}
2.1.2 Set接口
-
概述
- 存储无序的,不可重复数据
- 实现类:HashSet类、LinkedHashSet类、TreeSet类
-
无序性(以HashSet为例)
- 无序性不等于随机性。
- 存储数据在底层数组中并非按照索引的顺序添加,而是根据数据的哈希值
-
不可重复性
- 保证添加的元素按照equals()判断时,不能返回true。即:相同元素只能添加一个
-
添加元素的过程(HashSet为例)
- 如果此位置上没有元素,则a添加成功
- 如果此位置有其他元素b(或以链表形式存在的多个元素),则比较元素a与元素b的哈希值:如果哈希值不相同则元素a添加成功。
- 如果哈希值相同则调用a所在类的equals方法,若方法返回true,则元素添加失败,若返回false则添加成功。
- 注意:HashSet底层是以数组加链表的方式存储的
-
代码练习
public class SetTest {
@Test
public void test(){
HashSet set=new HashSet();
set.add(123);
set.add(456);
set.add(123);
set.add("AA");
set.add("BB");
set.add("CCCCC");
set.add(new Person("haha",18));
set.add(new Person("haha",18));
Iterator iterator = set.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
}
@Test
public void test2(){
//LinkedHashSet()作为HashSet的子类,在添加数据时,每个数据还
// 维护了两个引用,构建了一个链表,便于频繁的遍历操作
HashSet set=new LinkedHashSet();
set.add(123);
set.add(456);
set.add(123);
set.add("AA");
set.add("BB");
set.add("CCCCC");
set.add(new Person("haha",18));
set.add(new Person("haha",18));
Iterator iterator = set.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
}
@Test
public void test3(){
/**
* 1、向TreeSet中添加数据要添加相同类的对象
* 2、两种排序方式:自然排序 定制排序
*/
TreeSet set=new TreeSet();
set.add(new Person("Tom",18));
set.add(new Person("Jack",16));
set.add(new Person("Jim",20));
set.add(new Person("Tom",19));
set.add(new Person("Jerry",30));
Iterator iterator = set.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
}
@Test
public void test4(){
Comparator com=new Comparator() {
@Override
public int compare(Object o1, Object o2) {
if(o1 instanceof Person&& o2 instanceof Person){
Person p1=(Person)o1;
Person p2=(Person)o2;
return Integer.compare(p1.getAge(),p2.getAge());
}else{
throw new RuntimeException("输入的数据类型不匹配!");
}
}
};
TreeSet set=new TreeSet(com);
set.add(new Person("Tom",18));
set.add(new Person("Jack",16));
set.add(new Person("Jim",20));
set.add(new Person("Tom",19));
set.add(new Person("Jerry",30));
Iterator iterator = set.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
}
}
2.2 Map接口
2.2.1 概述
- 概述
- 双列数据,存储key—value对的数据
- 实现类
- HashMap类:作为Map的主要实现类;线程不安全,效率高;可以存储null的key或value
- LinkedHashMap类:能够保证遍历Map元素时,可以按照添加的顺序实现遍历。
- 原因:在原来的HashMap底层结构基础上,添加了一对指针,指向前一个和后一个元素。对于频繁的遍历操作,此类执行效率比较高。
- TreeMap类:保证按照添加的 key–value 对进行排序,实现排序遍历。(此时考虑key的自然排序和定制排序)
- HashTable:作为古老实现类;线程安全,效率高低。
- Properties类:常用来处理配置文件。key 和 value都是String类型。
- 注意:数组+链表 (jdk7及之前)数组+链表+红黑树(jdk 8)
2.2.2 Map集合结构的理解
- Map中的key
- 无序的、不可重复的,使用Set进行存储key
- 重写equals()和hashCode()方法(以HashMap为例)
- Map中的value
- 无序的、可重复的,使用Collection存储所有的value
- 键值对
- key-value构成了一个Entry对象。 Map中的entry:无序的、不可重复的,使用Set存储所有Entry。
2.2.3 HashMap底层实现原理
- 以jdk 7为例
- HashMap map = new HashMap()
- 在实例化以后,底层创建了长度是16的一维数组Entry[] table
- map.put(key1,value1):添加元素
- 调用key1所在类的hashCode()计算key1哈希值,此时哈希值经过某种算法计算以后,得到在Entry数组中的存放位置。
- 如果此位置上位置为空,则key1和value1添加成功。
- 如果此位置不为空,即此位置上有一个或多个(以链表形式存在)数据,比较key1和已经存在的一个或多个数据的哈希值
- 如果key1的哈希值与已经存在的哈希值都不相同,此时key1–value1添加成功。(数据以链表形式存储)
- 如果key1的哈希值和已经存在的某一个元素的哈希值相同,继续比较:调用key1所在类的equals()方法,比较
- 如果equals()方法返回false:此时key1–value1添加成功。(数据以链表形式存储)
- 如果equals()返回true:使用value替换相同key的value值。
- jdk 8和jdk 7在底层实现的不同
- new HashMap ():底层没有创建一个长度为16的数组
- jdk 8底层的数组是:Node[],而不是Entry[]
- 首次调用put()方法时,底层创建长度为16 的数组
- jdk 7底层结构只有:数组+链表,jdk 8中底层结构是:数组+链表+红黑树
- 当数组的某一个索引的位置上的元素以链表形式存在的数据个数>8且当前数组的长度超过>64时,此时索引位置上的所有数据改为红黑树存储
2.2.4 代码示例
public class MapTest {
@Test
public void MapTest(){
// Map map=new Hashtable();
Map map=new HashMap();
//添加
map.put("AA",123);
map.put("BB",456);
map.put("CC",789);
//修改
map.put("AA",23);
System.out.println(map);
Map map1=new HashMap();
map1.put("DD",123);
map1.put("EE",456);
map.putAll(map1);
System.out.println(map);
//remove(Object key)
Object value = map.remove("AA");
System.out.println(value);
System.out.println(map);
}
@Test
public void test1(){
Map map=new HashMap();
map.put("AA",123);
map.put("BB",456);
map.put("CC",789);
//get(Object key);
System.out.println(map.get("AA"));
//containsKey(Object key):
boolean key = map.containsKey("AA");
System.out.println(key);
//
boolean value = map.containsValue(123);
System.out.println(value);
}
@Test
public void test2(){
Map map=new HashMap();
map.put("AA",123);
map.put("BB",456);
map.put("CC",789);
//遍历所有的key集:keySet()
Set set = map.keySet();
Iterator iterator = set.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
System.out.println("------------------------------------------");
//遍历所有的value集:values()
Collection values = map.values();
for (Object obj:values) {
System.out.println(obj);
}
//遍历所有key-values entrySet();
Set set1 = map.entrySet();
Iterator iterator1 = set1.iterator();
while(iterator1.hasNext()){
Object obj=iterator1.next();
//entrySet集合中的元素都是entry
Map.Entry entry= (Map.Entry) obj;
System.out.println(entry.getKey()+"---->"+entry.getValue());
}
// System.out.println(map);
}
}
三、Properties
3.1 概述
- Properties类是Hashtable的子类,该对象用于处理属性配置文件
- key和value都是String类型
3.2 代码演示
public class Test {
public static void main(String[] args) {
Properties p = new Properties();
FileInputStream inputStream = null;
try {
//获取输入流
inputStream = new FileInputStream("./src/jdbc.properties");
p.load(inputStream);
//通过key得到值
String user = p.getProperty("user");
String driver = p.getProperty("driver");
System.out.println(user + "\n" + driver);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (inputStream != null) {
inputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
四、Collections工具类
4.1 概述
- Collections类提供了操作集合的一些方法
4.2 常用方法
- reverse(List):反转List中元素的顺序
- shuffle(List):对List集合元素进行随机排序
- sort(List):根据元素的自然顺序对指定List集合元素按升序排序
- sort(List,Comparator):根据指定的Comparator产生的顺序对List集合元素进行排序
- swap(List,int,int):将指定list集合中的i处元素和j处元素进行交换
- Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素
- Object max(Collection,Comparator):根据Comparator指定的顺序,返回给定集合中最大的元素
- Object min(Collection)
- Object min(Collection,Comparator)
- int frequency(Collection,Object):返回指定集合中指定元素出现的次数
- void copy(List,dest,List src):将src中的内容复制到dest中
- boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替换List中对应的值
- Collections类中提供了多个synchronizedXxx()方法,该方法可以将指定集合包装成线程同步的集合,从而可以解决多线程并发访问集合时的线程安全问题