集合的继承关系
在java中集合分为两大类:
一类是单个方式存储元素
单个方式存储元素,这一类集合中超级父接口:java.util.Collection;
一类是以键值对儿的方式存储元素
以键值对的方式存储元素,这一类集合中超级父接口:java.util.Map;
我们先来了解Collection集合类
要了解集合,得先知道集合的继承关系
这是一个Collection集合的继承关系图,我们从上往下由浅到深来介绍
Collection
- Collection中能存放什么元素?
没有使用“泛型”之前,Collection中可以存储Object的所有子类型。
使用了“泛型”之后,Collection中只能存储某个具体的类型。
Collection中什么都能存, 只要是Object的子类型就行。(集合中不能直接存储基本数据类型,也不能存 java对象,只是存储java对象的内存地址。)
由继承图可知,这是一个所有子类的超级父接口,Collection接口中的方法都能被子类继承,来看看Collection中都有哪些方法吧。
Collection中的常用方法
- .add(Object e) 向集合中添加元素
// 创建一个集合对象
//Collection c = new Collection(); // 接口是抽象的,无法实例化。
// 创建集合对象,多态
Collection c = new ArrayList();
// 向集合中添加元素
c.add(1200); // 自动装箱(java5的新特性。),实际上是放进去了一个对象的内存地址。Integer x = new Integer(1200);
c.add(3.14); // 自动装箱
c.add(new Object());
c.add(new Student());
- . size() 获取集合中元素的个数
//创建集合对象
Collection c = new ArrayList();
// 向集合中添加元素
c.add(1200);
c.add(3.14);
c.add(new Object());
//获取集合中的元素个数
int x=c.size();//x=3
- .clear() 清空集合
//创建集合对象
Collection c = new ArrayList();
// 向集合中添加元素
c.add(1200);
c.add(3.14);
c.add(new Object());
//获取集合中的元素个数
int x=c.size();//x=3
//清空集合
c.clear();
//再获取集合中的元素个数
int x=c.size();//此时x=0
- contains(Object o) 判断当前集合中是否包含元素o,包含返回true,不包含返回false
//创建集合对象
Collection c = new ArrayList();
// 向集合中添加元素
c.add(1200);
c.add(3.14);
c.add(new Object());
boolean flag = c.contains(3.14);//true
boolean flag2 = c.contains(3.1415926);//false
深入Collection集合的contains方法:
boolean contains(Object o)
判断集合中是否包含某个对象o
如果包含返回true, 如果不包含返回false。
contains方法是用来判断集合中是否包含某个元素的方法,
那么它在底层是怎么判断集合中是否包含某个元素的呢?
是调用了equals方法进行比对。
equals方法返回true,就表示包含这个元素。
// 创建集合对象
Collection c = new ArrayList();
// 向集合中存储元素
String s1 = new String("abc"); // s1 = 0x1111
c.add(s1); // 放进去了一个"abc"
String s2 = new String("def"); // s2 = 0x2222
c.add(s2); // 放进去了一个"def"
// 集合中元素的个数
System.out.println("元素的个数是:" + c.size()); // 2
// 新建的对象String
String x = new String("abc"); // x = 0x5555
// 已知判断集合中是否包含某个元素是调用了equals方法
// 而Object 中equals方法比较的是两个对象的内存地址
// 那么c集合中是否包含x?结果猜测一下是true还是false?
System.out.println(c.contains(x)); //判断集合中是否存在"abc" true
不是说调用equals方法比较两个对象的内存地址吗,明明两个对象内存地址不一样
为什么是true呢?
为什么呢?因为集合中的元素是String类型,而String类重写了equals方法使得equals方法比较的是内容,而不是内存地址如果此时String没有重写equals方法 或者集合存储的是一个没有重写equals方法的类型对象呢?那么使用contains();方法便会出现问题,上面代码结果返回的结果便为false(因为它们调用的是Object的equals();方法,比较的是内存地址)
所以 存放在一个集合中的类型,一定要重写equals方法。
- .remove(Object o) 删除集合中的某个元素。
//创建集合对象
Collection c = new ArrayList();
// 向集合中添加元素
c.add(1200);
c.add(3.14);
c.add(new Object());
//获取集合中的元素个数
int x=c.size();//x=3
//删除集合中的某个元素
c.remove(1200);
//再获取集合中的元素个数
int x=c.size();//此时x=2
- .isEmpty() 判断该集合中元素的个数是否为0
//创建集合对象
Collection c = new ArrayList();
// 向集合中添加元素
c.add(1200);
c.add(3.14);
c.add(new Object());
//判断该集合中元素的个数是否为0
c.isEmpty(); //flase
//清空集合
c.clear();
//再判断该集合中元素的个数是否为0
c.isEmpty(); //true
迭代器
迭代器是用来遍历集合的,集合调用 .iterator() 方法即可获取迭代器
// 创建集合对象
Collection c1 = new ArrayList(); // ArrayList集合:有序可重复
// 添加元素
c1.add(1);
c1.add(2);
c1.add(3);
c1.add(4);
// 迭代集合,获取迭代器对象
Iterator it = c1.iterator();
while(it.hasNext()){
// 存进去是什么类型,取出来还是什么类型。
Object obj = it.next();
// 只不过在输出的时候会转换成字符串。因为这里println会调用toString()方法。
System.out.println(obj);
}
注意:
1、当集合的结构发生改变时,迭代器必须重新获取,如果还是用以前老的迭代器,会出现异常:java.util.ConcurrentModificationException
2、在迭代集合元素的过程中,不能调用集合对象的remove方法 删除元素 ,迭代过程中不能这样。会出现异常,如果要删除元素,一定要使用迭代器Iterator的remove方法,不要使用集合自带的remove方法删除元素。
// 创建集合
Collection c = new ArrayList();
// 注意:此时获取的迭代器,指向的是那是集合中没有元素状态下的迭代器。
// 一定要注意:集合结构只要发生改变,迭代器必须重新获取。
// 当集合结构发生了改变,迭代器没有重新获取时,调用next()方法时:java.util.ConcurrentModificationException
Iterator it = c.iterator();
// 添加元素
c.add(1); // Integer类型
c.add(2);
c.add(3);
// 获取迭代器
Iterator it = c.iterator();
while(it.hasNext()){
// 编写代码时next()方法返回值类型必须是Object。
Object obj = it.next();
System.out.println(obj);
}
//创建新集合
Collection c2 = new ArrayList();
c2.add("abc");
c2.add("def");
c2.add("xyz");
Iterator it2 = c2.iterator();
while(it2.hasNext()){
Object o = it2.next();
//c2.remove(o); 错误写法
// 删除元素,通过迭代器对象的remove()删除
it2.remove(); // 删除的一定是迭代器指向的当前元素。
// 删除元素之后,集合的结构发生了变化,应该重新去获取迭代器
// 但是,循环下一次的时候并没有重新获取迭代器,所以会出现异常:java.util.ConcurrentModificationException
// 出异常根本原因是:集合中元素删除了,但是没有更新迭代器(迭代器不知道集合变化了)
//c2.remove(o); // 直接通过集合去删除元素,没有通知迭代器。(导致迭代器的快照和原集合状态不同。)
// 使用迭代器来删除可以吗?
// 迭代器去删除时,会自动更新迭代器,并且更新集合(删除集合中的元素)。
System.out.println(o);
}
System.out.println(c2.size()); //0
}
}
超级父接口Collection中的方法已经介绍完了。现在说说list接口中的方法
list
1、List集合存储元素特点:有序可重复
有序:List集合中的元素有下标。从0开始,以1递增。
可重复:存储一个1,还可以再存储1.
2、List既然是Collection接口的子接口,那么肯定List接口有自己“特色”的方法:
以下只列出List接口特有的常用的方法:
- .add(int index, Object element) 在列表的指定位置插入指定元素(第一个参数是下标)
// 创建List类型的集合。
List myList = new ArrayList();
// 添加元素
myList.add("A"); // 默认都是向集合末尾添加元素。
myList.add("B");
//在列表的指定位置插入指定元素(第一个参数是下标)
// 这个方法使用不多,因为对于ArrayList集合来说效率比较低。
myList.add(2, "KING");
- .get(int index) 根据下标获取元素
// 创建List类型的集合。
List myList = new ArrayList();
// 添加元素
myList.add("A");
myList.add("B");
// 根据下标获取元素
Object s= myList.get(0);
System.out.println(s);// A
- . indexOf(Object o) 获取指定对象第一次出现处的索引。
// 创建List类型的集合。
List myList = new ArrayList();
// 添加元素
myList.add("A");
myList.add("B");
myList.add("B");
// 获取指定对象第一次出现处的索引。
System.out.println(myList.indexOf("B")); // 1
- lastIndexOf(Object o) 获取指定对象最后一次出现处的索引。
// 创建List类型的集合。
List myList = new ArrayList();
// 添加元素
myList.add("A");
myList.add("B");
myList.add("B");
// 获取指定对象最后一次出现的索引。
System.out.println(myList.lastIndexOf("B")); // 2
list 接口的方法了解一点,来看看list的实现类
ArrayList
1、默认初始化容量10(底层先创建了一个长度为0的数组,当添加第一个元素的时候,初始化容量10。)
2、集合底层是一个Object[]数组。
3、构造方法:
new ArrayList();
new ArrayList(20); 自定义初始化容量
4、ArrayList集合的扩容:
增长到原容量的1.5倍。
ArrayList集合底层是数组,怎么优化?
尽可能少的扩容。因为数组扩容效率比较低,建议在使用ArrayList集合
的时候预估计元素的个数,给定一个初始化容量。
5、数组优点:
检索效率比较高。(每个元素占用空间大小相同,内存地址是连续的,知道首元素内存地址,
然后知道下标,通过数学表达式计算出元素的内存地址,所以检索效率最高。)
6、数组缺点:
随机增删元素效率比较低。
另外数组无法存储大数据量。(很难找到一块非常巨大的连续的内存空间。)
7、向数组末尾添加元素,效率很高,不受影响。
8、面试官经常问的一个问题?
这么多的集合中,你用哪个集合最多?
答:ArrayList集合。
因为往数组末尾添加元素,效率不受影响。
另外,我们检索/查找某个元素的操作比较多。
9、ArrayList集合是非线程安全的。(不是线程安全的集合。)
LinkedList
关于LinkedList 我们只要记住以下几点
1、LinkedList 底层采用了双向链表数据结构
链表的优点:
由于链表上的元素在空间存储上内存地址不连续。
所以随机增删元素的时候不会有大量元素位移,因此随机增删效率较高。
在以后的开发中,如果遇到随机增删集合中元素的业务比较多时,建议
使用LinkedList。
链表的缺点:
不能通过数学表达式计算被查找元素的内存地址,每一次查找都是从头
节点开始遍历,直到找到为止。所以LinkedList集合检索/查找的效率
较低。
hashSet
数据实际存储在hashMap中的key部分,只要学习了hashMap
就知道了,在这里不重点讲解,可以看下面的hashMap部分
TreeSet
TreeSet集合存储元素特点:
1、无序不可重复的,但是存储的元素可以自动按照大小顺序排序!
称为:可排序集合。
2、无序:这里的无序指的是存进去的顺序和取出来的顺序不同。并且没有下标。
// 创建集合对象
Set<String> strs = new TreeSet<>();
// 添加元素
strs.add("A");
strs.add("B");
strs.add("Z");
strs.add("Y");
strs.add("Z");
// 遍历
for(String s : strs){
System.out.print(s);//A B Y Z
}
}
对自定义的类型来说,TreeSet可以排序吗?
需要定义排序规则之后,才可以排序。如何定义规则?
第一种方式:实现Comparable接口
public static void main(String[] args) {
//创建 Customer对象
Customer c1 = new Customer(32);
Customer c2 = new Customer(20);
Customer c3 = new Customer(30);
Customer c4 = new Customer(25);
// 创建TreeSet集合
TreeSet<Customer> customers = new TreeSet<>();
// 添加元素
customers.add(c1);
customers.add(c2);
customers.add(c3);
customers.add(c4);
// 遍历
for (Customer c : customers){
System.out.println(c);
}
}
}
// 放在TreeSet集合中的元素需要实现java.lang.Comparable接口。
// 并且实现compareTo方法。equals可以不写。
class Customer implements Comparable<Customer>{
int age;
public Customer(int age){
this.age = age;
}
// 需要在这个方法中编写比较的逻辑,或者说比较的规则,按照什么进行比较!
// k.compareTo(t.key)
// 拿着参数k和集合中的每一个k进行比较,返回值可能是>0 <0 =0
// 比较规则最终还是由程序员指定的:例如按照年龄升序。或者按照年龄降序。
//实现compareTo方法
public int compareTo(Customer c) {
return c.age - this.age;
}
public String toString(){
return "Customer[age="+age+"]";
}
}
第二种方式:使用比较器的方式。
public static void main(String[] args) {
// 创建TreeSet集合的时候,需要使用这个比较器。
//这样不行,没有通过构造方法传递一个比较器进去。
// TreeSet<WuGui> wuGuis = new TreeSet<>();
// 给构造方法传递一个比较器。
//TreeSet<WuGui> wuGuis = new TreeSet<>(new WuGuiComparator());
// 大家可以使用匿名内部类的方式(这个类没有名字。直接new接口。)
TreeSet<WuGui> wuGuis = new TreeSet<>(new Comparator<WuGui>() {
@Override
public int compare(WuGui o1, WuGui o2) {
return o1.age - o2.age;
}
});
wuGuis.add(new WuGui(1000));
wuGuis.add(new WuGui(800));
wuGuis.add(new WuGui(810));
for(WuGui wuGui : wuGuis){
System.out.println(wuGui);
}
}
}
// 乌龟
class WuGui{
int age;
public WuGui(int age){
this.age = age;
}
public String toString() {
return "小乌龟[" +
"age=" + age +
']';
}
}
// 单独在这里编写一个比较器
// 比较器实现java.util.Comparator接口。
class WuGuiComparator implements Comparator<WuGui> {
public int compare(WuGui o1, WuGui o2) {
// 指定比较规则
// 按照年龄排序
return o1.age - o2.age;
}
}
最终的结论:
放到TreeSet或者TreeMap集合key部分的元素要想做到排序,包括两种方式:
第一种 放在集合中的元素实现java.lang.Comparable接口。
第二种 在构造TreeSet或者TreeMap集合的时候给它传一个比较器对象。
Comparable和Comparator怎么选择呢?
当比较规则不会发生改变的时候,或者说当比较规则只有1个的时候,建议实现Comparable接口。
如果比较规则有多个,并且需要多个比较规则之间频繁切换,建议使用Comparator接口。
Comparator接口的设计符合OCP原则。
3、TreeSet集合底层实际上是一个TreeMap。TreeMap集合底层是一个二叉树。放到TreeSet集合中的元素,等同于放到TreeMap集合key部分了。
map
map集合的继承关系
map集合的常用方法
1、Map和Collection没有继承关系。
2、Map集合以key和value的方式存储数据:键值对
key和value都是引用数据类型。
key和value都是存储对象的内存地址。
key起到主导的地位,value是key的一个附属品。
方法
- .put(K key, V value) 向Map集合中添加键值对
// 创建Map集合对象
Map<Integer, String> map = new HashMap<>();
// 向Map集合中添加键值对
map.put(1, "zhangsan"); // 1在这里进行了自动装箱。
map.put(2, "lisi");
- .get(Object key) 通过key获取value
// 创建Map集合对象
Map<Integer, String> map = new HashMap<>();
// 向Map集合中添加键值对
map.put(1, "zhangsan"); // 1在这里进行了自动装箱。
map.put(2, "lisi");
// 通过key获取value
String value = map.get(2);
System.out.println(value);// lisi
- .size() 获取Map集合中键值对的个数。
//创建Map集合对象
Map<Integer, String> map = new HashMap<>();
// 向Map集合中添加键值对
map.put(1, "zhangsan"); // 1在这里进行了自动装箱。
map.put(2, "lisi");
//获取Map集合中键值对的个数
int s=map.size();
System.out.println("键值对的数量:" + s);//2
- .clear() 清空Map集合
Map<Integer, String> map = new HashMap<>();
// 向Map集合中添加键值对
map.put(1, "zhangsan"); // 1在这里进行了自动装箱。
map.put(2, "lisi");
//获取Map集合中键值对的个数
int s=map.size();
System.out.println("键值对的数量:" + s);//2
// 清空map集合
map.clear();
System.out.println("键值对的数量:" + map.size());//0
- .containsKey(Object key) 判断Map中是否包含某个key
Map<Integer, String> map = new HashMap<>();
// 向Map集合中添加键值对
map.put(1, "zhangsan"); // 1在这里进行了自动装箱。
map.put(2, "lisi");
// 判断是否包含某个key
// contains方法底层调用的都是equals进行比对的,所以自定义的类型需要重写equals方法。
System.out.println(map.containsKey(new Integer(2))); // true
- containsValue(Object value) 判断Map中是否包含某个value
Map<Integer, String> map = new HashMap<>();
// 向Map集合中添加键值对
map.put(1, "zhangsan"); // 1在这里进行了自动装箱。
map.put(2, "lisi");
// 判断是否包含某个value
System.out.println(map.containsValue(new String("lisi"))); // true
- remove(Object key) 通过key删除键值对
Map<Integer, String> map = new HashMap<>();
// 向Map集合中添加键值对
map.put(1, "zhangsan"); // 1在这里进行了自动装箱。
map.put(2, "lisi");
// 通过key删除key-value
map.remove(2);
System.out.println("键值对的数量:" + map.size());// 1
- Collection<> values() 获取Map集合中所有的value,返回一个Collection
Map<Integer, String> map = new HashMap<>();
// 向Map集合中添加键值对
map.put(1, "zhangsan"); // 1在这里进行了自动装箱。
map.put(2, "lisi");
// 获取所有的value
Collection<String> values = map.values();
// foreach
for(String s : values){
System.out.println(s);//zhangsan
} //lisi
- Set<> keySet() 获取Map集合所有的key(所有的键是一个set集合)
Map<Integer, String> map = new HashMap<>();
// 向Map集合中添加键值对
map.put(1, "zhangsan"); // 1在这里进行了自动装箱。
map.put(2, "lisi");
// 获取所有的key
Set<String> set=map.keySet();
// foreach
for(String s : set){
System.out.println(s);//1
} //2
- Set<Map.Entry<K,V>> entrySet() , 将Map集合转换成Set集合
假设现在有一个Map集合,如下所示:
map1集合对象
key | value |
---|---|
1 | zhang |
2 | lisi |
3 | wangwu |
Set set =map1.entrySet();
set集合对象中的元素:
1=zhangsan 【注意:Map集合通过entrySet()方法转换成的这个Set集合,Set集合中元素的类型是 Map.Entry<K,V>】
2=lisi 【Map.Entry和String一样,都是一种类型的名字,只不过:Map.Entry是静态内部类,是Map中的静态内部类】
3=wangwu
4=zhaoliu
Map集合的遍历。【非常重要】
第一种方式:获取所有的key,通过遍历key,来遍历value
//创建Map集合
Map<Integer, String> map = new HashMap<>();
//添加元素
map.put(1, "zhangsan");
map.put(2, "lisi");
map.put(3, "wangwu");
map.put(4, "zhaoliu");
// 遍历Map集合
// 获取所有的key,所有的key是一个Set集合
Set<Integer> keys = map.keySet();
// 遍历key,通过key获取value
// 迭代器可以
/*Iterator<Integer> it = keys.iterator();
while(it.hasNext()){
// 取出其中一个key
Integer key = it.next();
// 通过key获取value
String value = map.get(key);
System.out.println(key + "=" + value);
}*/
// foreach也可以
for(Integer key : keys){
System.out.println(key + "=" + map.get(key));
}
第二种方式:Set<Map.Entry<K,V>> entrySet()
// 以下这个方法是把Map集合直接全部转换成Set集合。
// Set集合中元素的类型是:Map.Entry
Set<Map.Entry<Integer,String>> set = map.entrySet();
// 遍历Set集合,每一次取出一个Node
// 迭代器
/*Iterator<Map.Entry<Integer,String>> it2 = set.iterator();
while(it2.hasNext()){
Map.Entry<Integer,String> node = it2.next();
Integer key = node.getKey();
String value = node.getValue();
System.out.println(key + "=" + value);
}*/
// foreach
// 这种方式效率比较高,因为获取key和value都是直接从node对象中获取的属性值。
// 这种方式比较适合于大数据量。
for(Map.Entry<Integer,String> node : set){
System.out.println(node.getKey() + "--->" + node.getValue());
}
}
hashMap
1、HashMap集合底层是哈希表/散列表的数据结构。
2、哈希表是一个怎样的数据结构呢?
哈希表是一个数组和单向链表的结合体。
数组:在查询方面效率很高,随机增删方面效率很低。
单向链表:在随机增删方面效率较高,在查询方面效率很低。
哈希表将以上的两种数据结构融合在一起,充分发挥它们各自的优点。
3、HashMap集合底层的源代码:
public class HashMap{
// HashMap底层实际上就是一个数组。(一维数组)
Node<K,V>[] table;
// 静态的内部类HashMap.Node
static class Node<K,V> {
final int hash; // 哈希值(哈希值是key的hashCode()方法的执行结果。hash值通过哈希函数/算法,可以转换存储成数组的下标。)
final K key; // 存储到Map集合中的那个key
V value; // 存储到Map集合中的那个value
Node<K,V> next; // 下一个节点的内存地址。
}
}
哈希表/散列表:一维数组,这个数组中每一个元素是一个单向链表。(数组和链表的结合体。)
4、最主要掌握的是:
map.put(k,v)
v = map.get(k)
以上这两个方法的实现原理,是必须掌握的。
5、HashMap集合的key部分特点:
无序,不可重复。
为什么无序? 因为不一定挂到哪个单向链表上。
不可重复是怎么保证的? equals方法来保证HashMap集合的key不可重复。
如果key重复了,value会覆盖。 放在HashMap集合key部分的元素其实就是放到HashSet集合中了。所以HashSet集合中的元素也需要同时重写hashCode()+equals()方法。
6、哈希表HashMap使用不当时无法发挥性能!
假设将所有的hashCode()方法返回值固定为某个值,那么会导致底层哈希表变成了纯单向链表。这种情况我们成为:散列分布不均匀。
什么是散列分布均匀?
假设有100个元素,10个单向链表,那么每个单向链表上有10个节点,这是最好的, 是散列分布均匀的。
假设将所有的hashCode()方法返回值都设定为不一样的值,可以吗,有什么问题?
不行,因为这样的话导致底层哈希表就成为一维数组了,没有链表的概念了。
也是散列分布不均匀。 散列分布均匀需要你重写hashCode()方法时有一定的技巧。
7、重点:放在HashMap集合key部分的元素,以及放在HashSet集合中的元素,需要同时重写hashCode和equals方法。
为什么呢?
向Map集合中存,以及从Map集合中取,都是先调用key的hashCode方法,然后再调用equals方法!equals方法有可能调用,也有可能不调用。
拿put(k,v)举例,什么时候equals不会调用?
k.hashCode()方法返回哈希值,
哈希值经过哈希算法转换成数组下标。
数组下标位置上如果是null,equals不需要执行。
拿get(k)举例,什么时候equals不会调用?
k.hashCode()方法返回哈希值,
哈希值经过哈希算法转换成数组下标。
数组下标位置上如果是null,equals不需要执行。
对于哈希表数据结构来说:
如果o1和o2的hash值相同,一定是放到同一个单向链表上。
当然如果o1和o2的hash值不同,但由于哈希算法执行结束之后转换的数组下标可能相同,此时会发生“哈希碰撞”。
扩展:HashMap集合key部分允许null,value也允许null
8、HashMap集合的默认初始化容量是16,默认加载因子是0.75
这个默认加载因子是当HashMap集合底层数组的容量达到75%的时候,数组开始扩容。
重点:HashMap集合初始化容量必须是2的倍数,这也是官方推荐的,
这是因为达到散列均匀,为了提高HashMap集合的存取效率,所必须的。
Hashtable
Hashtable的key可以为null吗?
Hashtable的key和value都是不能为null的。
HashMap集合的key和value都是可以为null的。
Hashtable方法都带有synchronized:线程安全的。
线程安全有其它的方案,这个Hashtable对线程的处理
导致效率较低,使用较少了。
Hashtable和HashMap一样,底层都是哈希表数据结构。
Hashtable的初始化容量是11,默认加载因子是:0.75f
Hashtable的扩容是:原容量 * 2 + 1
Properties属性类
Properties是一个Map集合,继承Hashtable,Properties的key和value都是String类型。
Properties被称为属性类对象。Properties是线程安全的。
Properties属性类的基本方法
// 创建一个Properties对象
Properties pro = new Properties();
// 需要掌握Properties的两个方法,一个存,一个取。
pro.setProperty("driver","com.mysql.jdbc.Driver");
pro.setProperty("username", "root");
pro.setProperty("password", "123");
// 通过key获取value(取)
String driver = pro.getProperty("driver");
String username = pro.getProperty("username");
String password = pro.getProperty("password");
System.out.println(url);
System.out.println(driver);
System.out.println(username);
System.out.println(password);
}
}
treeMap
treeMap与treeSet差不多,在这里就不过多的介绍了
可以看上面的treeSet部分
java.util.Collections 集合工具类
java.util.Collection 集合接口
java.util.Collections 集合工具类,方便集合的操作。
// ArrayList集合不是线程安全的。
List<String> list = new ArrayList<>();
// 变成线程安全的
Collections.synchronizedList(list);
// 排序
list.add("abf");
list.add("abx");
list.add("abc");
list.add("abe");
Collections.sort(list);
for(String s : list){
System.out.println(s);
}
// 注意:对List集合中元素排序,需要保证List集合中的元素实现了:Comparable接口。
Collections.sort(wuGuis);
for(WuGui2 wg : wuGuis){
System.out.println(wg);
}
// 对Set集合怎么排序呢?
Set<String> set = new HashSet<>();
set.add("king");
set.add("kingsoft");
set.add("king2");
set.add("king1");
// 将Set集合转换成List集合
List<String> myList = new ArrayList<>(set);
Collections.sort(myList);
for(String s : myList) {
System.out.println(s);
}
// 这种方式也可以排序。
//Collections.sort(list集合, 比较器对象);
}
}
集合的知识就这么多,感兴趣的可以去了解一下它们底层的数据结构,已经方法的实现,集合最最最重要的是,要掌握各类集合的 增删改查
主要的集合类:
ArrayList
LinkedList
HashSet (HashMap的key,存储在HashMap集合key的元素需要同时重写hashCode + equals)
TreeSet
HashMap
Properties
TreeMap