JAVA学习第三篇:集合框架
1,集合框架是java提供的方便用户存储数据工具,通过使用集合框架,开发者可以省去大量的时间在基础的数据结构设计上,从而提高开发效率
2,集合框架分为Collection 和 Map,其中Collection包括Set,List,Queue。并且所以的Collection类都可以通过Iterator进行迭代。Map保存的是key-value,在Map中key是不能重复的,value是可重复的。所以利用代码的重用性,Map将所有的value置为空就是Set, key不能重用,但value可以重复,这就是List。Map实现的子类有HashMap
3,Set详解
Set中不能包含相同元素,在此处的相同元素通过equals()方法判断。所以在元素重写equals()方法时,开发者需要特别的小心。
3.1 HashSet是Set的实现类,HashSet判断元素的相等是通过equals()和hashCode()判断,既equals()相等且hashCode()相等,则元素相等。当元素相等时,HashSet将拒绝加入该元素。在HashSet中元素的排列顺序是根据hashCode()返回值决定的。如
class A {
@Override
public boolean equals(Object obj) {
return true;
}
}
class B {
@Override
public int hashCode() {
return 100;
}
}
class C{
@Override
public int hashCode() {
return 2000;
}
@Override
public boolean equals(Object obj) {
return true;
}
}
public static void main(String[] args) {
A a1=new A();
A a2=new A();
B b1=new B();
B b2=new B();
C c1=new C();
C c2=new C();
HashSet books=new HashSet<>();
books.add(a1);
books.add(a2);
books.add(b1);
books.add(b2);
books.add(c1);
books.add(c2);
System.out.println(books);
}
在main方法中,books集合增加了多个元素,其中A重载了equals()方法,因为HashSet判断两个元素相等是通过equals()和hashCode()判断,所以,一个equals()返回true不会导致下一个元素不能加入。从而,两个A都被加入books。同理B只重载了hashCode()方法而没有重载equals()方法,所以两个B 都加入进来了。而C类因为重载了两个方法,并且返回值固定,equals()返回true,hashCode()返回2000,所以HashSet认为这两个C相同,只能加入一个C,最后结果是
[[email protected], [email protected], [email protected], [email protected], [email protected]]
3.2 LinkedHashSet继承自HashSet,同样,LinkedHashSet判断两个元素相等需要equals()和hashCode()两个方法,但是元素排序时是根据插入顺序决定的,先插入的在前,后插入的在后。如
LinkedHashSet notes=new LinkedHashSet<>();
notes.add(a1);
notes.add(a2);
notes.add(b1);
notes.add(b2);
notes.add(c1);
notes.add(c2);
System.out.println(notes);
同HashSet一样,notes将加入两个A,两个B,一个C,它加入的顺序如下
[[email protected], [email protected], [email protected], [email protected], [email protected]]
对比HashSet,a2插入在第二个。由此可见,LinkedHashSet的顺序就是插入顺序。
3.3 TreeSet 继承Set,在TreeSet中的所有元素都将被排好序,从大到小升序排列,是一棵红黑树。如
TreeSet trees=new TreeSet<>();
trees.add(2);
trees.add(6);
trees.add(1);
trees.add(4);
trees.add(4);
trees.add(10);
System.out.println(trees);
将输出
[1, 2, 4, 6, 10]
其中重复的4被忽略。在TreeSet中有几实用方法,first()返回第一个元素,last()返回最后一个元素,headSet(5)返回小于5的元素且不包括5,tailSet(5) 返回大于5的元素并包括5,subSet(1,3)返回[1,3)的元素。
3.4 EnumSet直接继承Set,但是无法直接new出来,他的初始化方法包括以下几个
enum e{
a,b,c,d
}
EnumSet seasons=EnumSet.allOf(e.class);
System.out.println(seasons);
seasons=EnumSet.noneOf(e.class);
seasons.add(e.b);
seasons.add(e.c);
System.out.println(seasons);
seasons=EnumSet.of(e.a,e.a);
System.out.println(seasons);
4. List详解
在List中,允许重复元素,在元素插入的过程中,List会给每个插入的元素设置索引,通过该索引List可以很快的找到该元素
4.1 ArrayList 继承List,他通过动态的分配内存而增加元素。如下
ArrayList books=new ArrayList<>();
books.add("b1");
books.add("b2");
books.add("b3");
books.add("b4");
books.add("b5");
books.add("b6");
books.add("b7");
System.out.println(books);
最终的结果是
[b1, b2, b3, b4, b5, b6, b7]
该打印顺序与插入顺序一致。同时ArrayList提供了一些可用的方法,如
books.add(1,"insert before b2");
System.out.println(books);
// [b1, insert before b2, b2, b3, b4, b5, b6, b7]
books.remove(2);
System.out.println(books);
// [b1, insert before b2, b3, b4, b5, b6, b7]
books.set(4, "replace b5");
System.out.println(books);
// [b1, insert before b2, b3, b4, replace b5, b6, b7]
System.out.println(books.subList(0, 4));
// [b1, insert before b2, b3, b4]
4.2 Stack继承Vector,而Vector继承List,在Stack中,元素遵循后进先出的原则,具体如下
Stack stack=new Stack<>();
stack.push("s1");
stack.push("s2");
stack.push("s3");
stack.push("s4");
System.out.println(stack);
// [s1, s2, s3, s4]
System.out.println(stack.peek());
// s4
System.out.println(stack);
// [s1, s2, s3, s4]
System.out.println(stack.pop());
// s4
System.out.println(stack);
//[s1, s2, s3]
peek()方法返回栈顶元素,但并不弹出。而pop()方法返回并弹出栈顶元素。
4.3 LinkedList是继承List,是一个双向的队列。初始化如下;
LinkedList dequeue = new LinkedList<>();
dequeue.offer("d1");
dequeue.push("d2");
dequeue.offerFirst("d0");
dequeue.offerLast("d3");
System.out.println(dequeue);
输出
[d0, d2, d1, d3]
在目前的研究中发现,offerFirst()和push()实现同样功能,offerLast()和offer()实现相同功能。
5 Queue详解
队列是一种先进先出的数据结构,不允许随机访问元素
5.1 PriorityQueue继承Queue。具体使用如下
PriorityQueue queue=new PriorityQueue<>();
queue.add("q1");
queue.add("q2");
queue.add("q3");
queue.add("q4");
queue.add("q5");
System.out.println(queue);
// [q1, q2, q3, q4, q5]
System.out.println(queue.poll());
//q1
System.out.println(queue);
//[q2, q4, q3, q5]
poll()方法将队首元素出队列,并且在队列中删除该元素。
5.2 ArrayQueue基于数组的队列,所以随机访问快,具体如下
ArrayDeque stack=new ArrayDeque<>();
stack.push(1);
stack.push(2);
stack.push(4);
stack.push(3);
System.out.println(stack);
// [3, 4, 2, 1]
System.out.println(stack.peek());
//3
System.out.println(stack);
//[3, 4, 2, 1]
System.out.println(stack.pop());
//3
System.out.println(stack);
//[4, 2, 1]
6 迭代Collection
每一种Collection的实现类都有iterator()方法,通过该方法可以迭代该集合,如;
ArrayList a=new ArrayList<>();
a.add(1);
a.add(2);
Iterator iterator= a.iterator();
while(iterator.hasNext()) {
System.out.println(iterator.next());
}
最终输出1,2
7 Map实现的子类
7.1 HashMap 和HashTable,这两个子类通过equals()和hashCode()方法一起判断元素是否相等。
class MapA {
int count;
public MapA(int count) {
this.count = count;
}
@Override
public int hashCode() {
// TODO Auto-generated method stub
return count;
}
@Override
public boolean equals(Object obj) {
// TODO Auto-generated method stub
return true;
}
}
class MapB{
@Override
public boolean equals(Object obj) {
// TODO Auto-generated method stub
return true;
}
}
main方法如下;
MapA a = new MapA(100);
MapA a2 = new MapA(100);
HashMap map = new HashMap<>();
map.put(a, "1");
map.put(a2, "2");
System.out.println(map);
MapB b=new MapB();
MapB b2=new MapB();
Hashtable taHashtable=new Hashtable<>();
taHashtable.put(b, "1");
taHashtable.put(b2, "2");
System.out.println(taHashtable);
输出
{[email protected]=2}
{[email protected]=2, [email protected]=1}
此处原理和HashSet一样。
7.2 LinkedHashMap是Map的链式存储方式。能够快速的增加和删除元素。
LinkedHashMap linkedHashMap=new LinkedHashMap<>();
linkedHashMap.put("a", 100);
linkedHashMap.put("b", 89);
for(Object key:linkedHashMap.keySet()) {
System.out.println(key+"-->"+linkedHashMap.get(key));
}
输出如下
a-->100
b-->89
7.3 Properties,该对象可以用来读写配置文件,如
Properties properties=new Properties();
properties.setProperty("username", "wudi");
properties.setProperty("password", "123456");
System.out.println(properties);
try {
properties.store(new FileOutputStream("test.txt"), "suit yourself");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
控制台输出
{password=123456, username=wudi}
刷新工程项目后,在src下会多一个test.txt文件。如下图
其中test.txt文件如下
一般我们看见的xml文件,也可以直接使用Properties进行读写