0%

java-Day10——集合

引入

数组存储的特点

  • 数组一旦初始化,长度就确定了

  • 数组中的多个元素是依次紧密排列的,有序的,可重复的。

  • 数组一旦初始化完成,其元素的类型就是确定的。不是此类型的,就不能添加到此数组中

  • 元素的类型可以是基本数据类型,也可以是引用数据类型

反向来看

  • 一旦初始化,长度就不可变了
  • 数组中存储元素特点的单一性。对于无须、不可重复的场景的多个数据就无能为力了
  • 数组中可用的方法、属性都很少。具体需要都需要自己来组织相关代码逻辑
  • 对于数组中元素的删除、插入操作,性能较差。

Java集合框架体系

1.java.util.Collection:存储一个个的数据

  • 子接口:List:存储有序的、可重复的数据
    • **ArrayList(主要)**、LinkedList、Vector
  • 子接口:**Set:**存储无序的、不可重复的接口
    • **HashSet(主要)**、LinkedHashSet、TreeSet

2**.java.util.Map:**存储一对一对的数据

  • **HashMap(主要)**、LinkedHashmap、TreeMap、Hashtable、Properties

Collection

常用方法

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
36
37
38
39
40
41
42
@Test
public void test1(){
//add
Collection coll = new ArrayList();
coll.add("aaa");
coll.add(123);//自动装箱
coll.add(new Object());
System.out.println(coll);

//addAll()
Collection coll1 = new ArrayList();
coll1.add("bbb");
coll1.add("fff");
//size()
System.out.println(coll.size());
coll.addAll(coll1);
System.out.println(coll);

//isEmpty()
System.out.println(coll.isEmpty());
//contains(Object obj)
System.out.println(coll.contains("aaa"));
//containsAll(Collection coll)
Collection coll3 = new ArrayList();
coll3.add("xx");
coll3.add("haha");
System.out.println(coll.containsAll(coll3));
// clear 清空集合元素
//remove(Object):从集合中删除第一个找到的与obj对象equals返回true的元素
//removeAll(Collection coll):从当前集合中删除所有与coll集合中相同的元素.即this
//retainAll)Collection coll):当当前集合中删除两个集合中不同的元素


//集合 --》数组
Object[] arr = coll.toArray();
System.out.println(Arrays.toString(arr));

//数组--》集合
String[] arr2 = new String[]{"aa","bb"};
Collection list = Arrays.asList(arr2);
System.out.println(list);
}

添加元素的要求:

要求元素所属的类一定要重写equals()

迭代器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Test
public void test(){
Collection coll = new ArrayList();
coll.add("aaa");
coll.add(123);
coll.add(new Object());

//获取迭代器对象
Iterator iterator = coll.iterator();
//实现遍历方式1:
System.out.println(iterator.next());
System.out.println(iterator.next());
System.out.println(iterator.next());
//实现遍历方式2:
while (iterator.hasNext()){
System.out.println(iterator.next());
}
}

foreach循环

格式:

for(要遍历的集合或数组元素的类型 临时变量: 要遍历的集合或数组变量){

​ 操作临时变量的输出

}

针对于集合来讲,增强for循环的底层仍然使用的是迭代器

增强for循环的执行过程中,是将集合或数组中的元素一次赋值给临时变量,注意循环体中对临时变量的修改,可能不会导致原有集合或数组中元素的修改。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Test
public void test2() {
Collection coll = new ArrayList();
coll.add("aaa");
coll.add(123);
coll.add(new Object());

for (Object obj : coll) {
System.out.println(obj);
}

int[] arr = new int[]{1,2,3,4,5};
for (Object i : arr) {
System.out.println(i);
}
}

List(Collection)

常用方法

1.collections中含有的15个方法

2.由于集合是有序的,进而就有与索引相关的一些方法

插入元素:

  • void add(int index, Object ele)

  • boolean addAll(int index, Collection eles)

获取元素

  • Object get(int index):获取指定index位置的元素
  • List subList(int fromIndex, int toIndex)返回从fromIndex到toIndex的位置的子集合

获取元素索引

  • int indexOf(Object obj):返回obj在集合中首次出现的位置
  • int lastIndexOf(Object obj):返回Obj在当前集合中末次出现的位置

删除和替换元素

  • Object remove(int index):移除指定index位置的元素,并返回此元素
  • Object set(int index, Object ele):设置指定index位置的元素为ele

小结:

:add(Object obj) addAll(Collection coll)

: remove(Object obj) remove(int index)

:set(int index, Object ele)

:get(int index)

:add(int index, Object ele) addAll(int index, Collection eles)

长度: size()

遍历:iterator(), foreach, for

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Test
public void test1(){
List list = new ArrayList();
list.add("AA");
list.add(123);
list.add("bb");
System.out.println(list.toString());

list.add(2,"Cc");
List list1 = Arrays.asList(1,2,3);

// list.add(1,list1); //将list1看作一个整体加入list
list.addAll(1,list1);
System.out.println(list);

list.remove(2);//删除索引为2的元素
list.remove(Integer.valueOf(2));//删除数据为2

}

实现类及其特点

ArrayList: List的主要实现类:线程不安全、效率高;底层使用Object[]数组存储。添加、查询数据时效率高;插入、删除时,效率较低

LinkedList: 底层使用双向链表进行存储。在对集合中的数据频繁进行删除和插入时建议使用此类。插入、删除时,效率高,添加、查询数据时效率低。

Vector:List的古老实现类:线程安全、效率低;底层使用Object存储数据

Set(Collection)

无序性、不可重复性的理解

无序性: 不是随机性。也不是添加元素的顺序和遍历元素的顺序的不一致。而是与添加元素位置有关,不像ArrayList一样是依次紧密排列的,而是根据添加元素的哈希值,计算的其在数组中存储的位置。此位置不是依次排列的,表现为无序性

不可重复性:添加到Set中的元素是不能相同的。比较的标准,需要判断hashCode()得到的哈希值与equals()得到的结果。

常用方法:

即为Collection中声明的15个抽象方法。没有新增的方法

开发场景

较List、Map来说,set使用的频率较少

实现类:

**HashSet:**主要实现类;底层使用HashMap,即使用数组+单向链表+红黑树结构进行存储

LinkedHashSet: 是HashSet的子类。在现有数组+单向链表+红黑结构基础上,又添加了一组双向链表,用于记录添加元素的先后顺序。即:我们可以按照添加元素的顺序实现遍历。便于频繁的查询操作。

TreeSet:底层使用红黑树存储。可以按照添加的元素的指定的属性的大小顺序进行遍历

添加到HashSet/LinkedHashSet中元素的要求:

要求元素所在的类要重写两个方法:equals()和hashCode().

同时要求equals()和hashCode()要保持一致性

TreeSet

向TreeSet中添加元素的要求

添加到TreeSet中的元素必须是同一个类型的对象,否则会报ClassCastException.

判断数据是否相同的标准:

  • 不再是考虑hashCode()和equals()方法了,也就意味着添加到TreeSet中的元素不再需要重新hashcode和equals()

  • 比较元素大小的或比较元素是否相等的标准就是考虑自然排序或定制排序中compareTo()或compare()的返回值。如果compareTo()或compare()的返回值为0,则认为两个对象是相等的。由于TreeSet中不能存放相同的元素,则后一个相等的元素就不能添加到TreeSet中。

Map

实现类及对比

  • HashMap:主要实现类;线程不安全,效率高;可以添加null的key和value的值;底层使用数组+单向链表+红黑树结构存储
    • LinkedHashMap:是HashMap的子类,在HashMap使用的结构基础上,增加了一对双向链表,用于记录添加的元素的先后顺序。遍历的时候可以按照添加的顺序显示。开发中,对于频繁的遍历操作,建议使用此类。
  • Hashtable:古老实现类;线程安全,效率低;不可以添加null的key和value值;底层使用数组+单向链表结构存储
  • TreeMap:底层使用红黑树存储;可以安装添加的key-value中key元素的指定的属性的大小顺序进行遍历。需要考虑1.自然排序 2.定制排序
    • Properties:其key和value都是String类型。常用来处理属性文件。

HashMap中元素的特点

  • HashMap中的所有的key彼此之间是不可以重复的、无序的。所有的key就构成了一个Set集合。 ==》key所在的类要重写hashCode()equals()
  • HashMap中的所有的value彼此之间是可重复的、无序的。所有的value就构成一个Collection集合。==》value所在的类要重写equals()
  • HashMap中的一个key-value就构成了一个Entry。
  • HashMap中所有的entry彼此之间是不可重复的、无序的。所有的entry就构成了一个set集合。

常用方法

添加、修改操作:

​ Object put(Object key, Object value):将指定key-value添加到当前map对象中

​ void putAll(Map m):将m中所有key-value对存放到当前map中

删除

​ Object remove(Object key) 移除指定key的key-value对,并返回value

​ void clear():清空当前map中所有的数据

元素查询

​ Object get(object key)获取指定key对应value

​ boolean containKey(Object key)是否包含指定的key

​ boolean containsValue(Object value):是否包含指定的value

​ int size():返回map中key-value对的个数

​ boolean isEmpty():判断当前map是否为空

​ boolean equals(Object obj):判断当前map和参数对象是否相等

元视图操作的方法

  • Set keySet() 返回所有key构成的Set集合
  • Collection values():返回所有value构成的Collection集合
  • Set entrySet():返回所有key-value对构成的Set集合

小结:

增:put(Object key, Object value), putAll(Map m)

删:Object remove(Object key)

改:put(Object key, Object value), putAll(Map m)

查:Object get(Object key)

长度:size()

遍历:

​ 遍历key集: Set keySet()

​ 遍历value集: Collection values()

​ 遍历entry集:Set entrySet()

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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
    @Test
public void test1(){
//put(Object key, Object value)
HashMap map = new HashMap();
map.put("AA", 56);
map.put(65,"TOM");
map.put("BB", 78);
System.out.println(map);

//size()
System.out.println(map.size());

//Object remove(Object key)
Object value = map.remove("AA");
System.out.println(map);

//修改:put
Object oldValue = map.put("BB",99);
System.out.println(oldValue);
System.out.println(map);

//get
Object value1 = map.get("BB");
System.out.println(value1);


//遍历key集
Set keySet = map.keySet();
//使用迭代器
Iterator iterator = keySet.iterator();
while(iterator.hasNext()){
Object key = iterator.next();
System.out.println(key);
}

//遍历Value集:
Collection values = map.values();
//方式1:for-each
for(Object obj: values){
System.out.println(obj);
}
//方式2:
Set keySet1 = map.keySet();
for(Object key:keySet1){
Object value2 = map.get(key);
System.out.println(value2);
}

//方式1:遍历entry集
Set entryset = map.entrySet();
Iterator iterator2 = entryset.iterator();
while(iterator.hasNext()){
//方法1
System.out.println(iterator.next());
//方法2
Map.Entry entry = (Map.Entry) iterator2.next();
System.out.println(entry.getKey()+"-->"+entry.getValue());

}

//方式2:遍历entry集
Set keySet2 = map.keySet();
for (Object key:keySet2){
System.out.println(key+ "--->"+map.get(key));
}
}
}

TreeMap的使用

  • 底层使用红黑树存储
  • 可以按照添加的key-value的key元素指定的属性大小顺序进行遍历
  • 需要考虑1.自然排序 2.定制排序
  • 要求向TreeMap中添加的key必须是同一个类型的对象
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
public class TreeMapTest {
@Test
public void test1(){
//自然排序
TreeMap map = new TreeMap();
map.put("CC", 89);
map.put("BB",78);
map.put("jj",new Data());
map.put("kk",78);

Set entrySet = map.entrySet();
for(Object entry:entrySet){
System.out.println(entry);
}
}
@Test
public void test2(){
TreeMap map = new TreeMap();

User u1 = new User("Tom", 23);
User u2 = new User("Jerry",43);
User u3 = new User("Rose",13);
User u4 = new User("Jack",23);
User u5 = new User("Tony", 33);

map.put(u1,78);
map.put(u2,76);
map.put(u3,76);
map.put(u4,77);
map.put(u5,45);

Set entrySet = map.entrySet();
for(Object entry:entrySet){
System.out.println(entry);
}

}

@Test
public void test3(){
//定制排序
Comparator comparator = new Comparator() {
@Override
public int compare(Object o1, Object o2) {
if(o1 instanceof User && o2 instanceof User) {
User u1 = (User) o1;
User u2 = (User) o2;

int value = u1.getName().compareTo(u2.getName());
if (value != 0) {
return value;
}
return u1.getAge() - u2.getAge();
}
throw new RuntimeException("类型不匹配");
}
};
TreeMap map1 = new TreeMap();
}
}


class User implements Comparable {
private String name;
private int age;

public User() {
}

public User(String name, int age) {
this.name = name;
this.age = age;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

@Override
//定义自然排序的规则
public int compareTo(Object o) {
if(this == o){
return 0;
}
if(o instanceof User){
User u = (User) o;
int value = this.age - u.age;
if(value !=0){
return value;
}
return -this.name.compareTo(u.name);
}
throw new RuntimeException("类型不匹配");
}

@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}

Properties的使用

Properties是Hashtable的子类,其key和value都是String类型的,常用来处理属性文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class PropertiesTest {
@Test
public void test() throws IOException {
//将数据封装到具体的配置文件中,在程序中读取配置文件中的信息,实现了数据和代码的解耦
File file = new File("info.properties");
System.out.println(file.getAbsolutePath());
FileInputStream fis = new FileInputStream(file);
Properties pros = new Properties();
pros.load(fis);//记载流中文件中的数据

//读取数据
String name = pros.getProperty("name");
String pwd = pros.getProperty("password");
System.out.println(name+"xx"+pwd);

fis.close();
}

}

Collections

Collections是一个操作Set,List和Map等集合的工具类。

**Question:**Collection和Collections

Collection:集合框架中的用于存储一个一个元素的接口,又为List和Set等子接口

Collections:用于操作集合框架的一个工具类。此时集合框架包括:Set、List、Map

常用方法

排序操作:

  • reverse(list):反转list中的元素

  • shuffle(list):对list集合元素进行随机排序

  • sort(list):根据元素的自然顺序对指定List集合元素按升序排序

  • sort(list.Comparator):根据指定的Comparator产生的顺序对List集合元素进行排序

  • swap(list.int int):将指定list集合中i处元素和j处元素进行交换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Test
public void test(){
List list = Arrays.asList(45,34,64,23,23,12,11,24,5);
System.out.println(list);
// Collections.reverse(list);
Collections.shuffle(list);
Collections.sort(list);
Collections.sort(list, new Comparator(){
@Override
public int compare(Object o1, Object o2) {
if(o1 instanceof Integer && o2 instanceof Integer){
Integer i1 = (Integer) o1;
Integer i2 = (Integer) o2;
return -(i1- i2);
}
throw new RuntimeException("类型不匹配");
}
});
System.out.println(list);
}

查找:

  • Object max(Collection):根据元素自然排序,返回集合中最大的元素
  • Object max(Collection.Comparator):根据Comparator指定的顺序,返回给定集合中最大元素
  • Object min(Collection):根据元素的自然顺序,返回给定集合中最小的元素
  • Object min(Collection Comparator):根据Comparator指定的顺序,返回给定集合中最小元素
  • int binarySearch(List list, T key)在List集合中查找某个元素的小标。
  • int binarySearch(List list, T key,Comparator c)在List集合中查找某个元素的小标,
  • int frequency(Collection c, Object o):返回指定集合中指定元素出现的次数

复制:

  • void copy(List des List src):将src中的内容赋值到dest中

    1
    2
    3
    List src = Arrays.asList(45,34,64,23,23,12,11,24,5);
    List dest = Arrays.asList(new Object[src.size()]);
    Collections.copy(dest,src);
  • boolean replaceAll(List list, Object oldVal, Object newVal):使用新值替换List对象中所有旧值

  • boolean addAll(Collection c, T..elements)将所有制定元素添加到指定collection中

  • Collections类中提供了多个synchronizedXXX()方法,该方法可使将指定集合包装成线程同步的集合

常见问题:

List,Set,Map是否为Collection的接口,三者的区别?

list,map,set接口的实现类,并说出其特点

集合的父类是谁?哪些安全的?

遍历集合的方式有哪些?

迭代器iterator用来遍历Collection,不能用来遍历Map

增强for

ArrayList与LinkedList区别?

Set里的元素是不能重复的,那用什么来区分重复与否,用equals()

hashCode()、equals()

TreeSet两种排序方式在使用的时候怎么起作用?

在添加新的的元素时,需要调用compareTo或compare()

TreeSet的数据结构

红黑树

final怎么用,修饰Map可以继续添加数据吗?

Set和Map的比较

HashSet底层是HashMap

LinkedHashSet底层就是LinkedHashMap

TreeSet底层就是TreeMap

HashMap线程安全吗?

不安全。

Hashtable是怎么实现爱你的,为什么安全?

数组+单向链表;底层方法使用synchronized修饰

HashMap和TreeMap的区别

底层数据结果截然不同

HashMap里面实践装的是什么?

JDK7:HashMap内部声明了Entry,实现了Map中Entry接口(key,value作为Entry两个属性出现)

JDK8:HashMap内部声明了Node,实现了Map中Entry接口(key,value作为Entry两个属性出现)

HashMap的key存储在哪里?

数组+链表+红黑树

自定义类型可以作为Key吗?

可以。要重写hashCode()和equals方法

-------------本文结束感谢您的阅读-------------