------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培
训、.Net培训</a>、期待与您交流! -------
-------------------Java 笔记之-----------------Java集合框架---------------
1)集合和数组
1. 数组可以保存多个对象(实际上是对象的引用变量),但长度不可变,所以不能保存数量变化的数据;而且无法保存具有映射关系的数据。
2. 为了保存数量不确定的数据,以及保存具有映射关系的数据,Java提供了集合类。主要负责保存、盛装其他数据,因此也被称为容器类。
3. 集合类和数组不一样,数组元素既可以是基本类型的值,也可以是对象(实际上保存的是对象的引用变量);
4. 而集合类里只能保存对象(实际上保存的是对象的引用变量)。
5. 容器可以管理对象的生命周期,对象与对象之间的依赖关系。
6. 集合中其实存储的都是对象的引用。迭代器取出的也是集合中的对象引用。
集合中可以直接存储基本数据类型。 因为自动装箱拆箱,会将基本数据类型都先封装成对象后才存入集合。
al.add(3);//al.add(new Integer(3));
集合特点:
1,用于存储对象的容器。
2,集合的长度是可变的。
3,集合中不可以存储基本数据类型值。
2)Java集合类主要由两个接口派生出:Collection和Map。
Collection—|------Set 有序集合;-------SortedSet
|------List 无序集合
|------Queue 是Java提供的队列实现。
|------Iterator------ListIterator
|------Comparator
|------Map 具有映射关系的数据-----SortedMap
Map的每项数据都是key-value对,key是不可重复的,用于标识集合里的每项数据,如需查阅根据key来取值。
List是接口,ArrayList才是具体的类。
常用集合类的继承结构如下:
Collection<--List<--Vector
Collection<--List<--ArrayList
Collection<--List<--LinkedList
Collection<--Set<--HashSet
Collection<--Set<--HashSet<--LinkedHashSet
Collection<--Set<--SortedSet<--TreeSet
Map<--SortedMap<--TreeMap
Map<--HashMap
3)Java集合可以分为Set(集)、List(列表)、Map(映射)三种体系,
1. Set(集)代表无序、不可重复的集合;
2. List(列表)代表有序、重复的集合;有角标
3. Map(映射)则代表具有映射关系的集合。Queue体系集合代表一种队列集合实现。
4)Collection:该接口中定义了集合的共性方法。
1,添加: boolean add(obj);
boolean addAll(Collection c)
2,删除: boolean remove(obj);
void clear(); 删除所有元素,是集合长度为0
3,判断: boolean contains(obj) 是否包含
boolean isEmpty():判断容器中是否有元素,依据的是size方法。
4,获取: Iterator iterator():迭代器。
5,交集: retainAll(Collection); 取交集
al.retainAll(a2); //将al集合中只保留与a2集合共同的元素。
6,个数: int size();
7,转成数组: T[] toArray(T[] t):
public class Demo1 {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("hello");
list.add(0, "world");
// 增加内容
Collections.addAll(list, "a", "b");
System.out.println("集合元素为:" + list);
// 内容反转保存
Collections.reverse(list);
System.out.println("内容反转保存" + list);
// 检索内容
int point = Collections.binarySearch(list, "a");
System.out.println("检索内容输出下标" + point);
point = Collections.binarySearch(list, "c");
System.out.println(point);
// 替换集合的内容
if (Collections.replaceAll(list, "hello", "替换")) {
System.out.println("替换集合的内容'hello'改为'替换'" + list);
}
// 集合排序
// 这里使用的String 类型排序,因为String类本身已经实现了Comparable接口
// 如果一个自定义类,一定要实现Comparable接口
Collections.sort(list);
System.out.println("集合排序" + list);
// 交换指定位置的元素
Collections.swap(list, 0, 2);
System.out.println("交换指定位置的元素0,2" + list);
}
}
6)Collection接口下的Iterator 接口
1.Iterator接口是Java集合框架的成员,主要用于遍历Collection集合中的元素,Iterator对象也被称为迭代器。
2.使用next() 获得集合中的下一个元素。
3.使用hasNext()检查序列中是否元素。
4.使用remove()将迭代器新返回的元素删除。
5.在每次调用next时,remove方法只能被调用一次 。
public class Demo__Iterator {
public static void main(String[] args) {
//实例化ArrayList接口
Collection collection = new ArrayList();
//加入元素
collection.add("s1");
collection.add("s2");
collection.add("s3");
Iterator iterator = collection.iterator();
// 得到一个迭代器
while (iterator.hasNext()) {
// 遍历
Object element = iterator.next();
//取出内容
System.out.println("iterator = " + element);
//输出内容
}
System.out.println("collection is not Empty! size="
+ collection.size());
Iterator iterator2 = collection.iterator();
// 得到一个迭代器
while (iterator2.hasNext()) {
//依次判断
Object element = iterator2.next();
//取出内容
System.out.println("remove: " + element);
iterator2.remove();
// 移除元素
if (collection.isEmpty()){
System.out.println("collection is Empty!");}
else{
System.out.println("collection is not Empty! size="
+ collection.size());}
}
Iterator iterator3 = collection.iterator();
if (iterator3.hasNext()) {
// 察看是否还有元素
System.out.println("还有元素");
}else if (collection.isEmpty()){
System.out.println("collection is Empty!");
}
// 使用collection.isEmpty()方法来判断
}
}
//如果要创建Iterator对象,则必须有一个被迭代的集合。
//当使用Iterator迭代访问集合元素时,只有通过Iterator的remove方法删除上一次next方法返回集合元素才可以改变集合。
8)Set集合
1. Set与Collection方法一致,只是Set不允许包含重复元素。
2. Set集合不允许包含相同的元素,如果把两个相同的元素加入一个Set集合,则添加失败。
3. Set集合中的对象是无序的,对集合中成员的访问和操作是通过对象的引用进行的,所以集中不能有重复对象。
4.加入Set的Object必须定义equals方法,确保元素唯一。
9)HashSet类
(1)HashSet是Set接口的实现。数据结构是:哈希表。
(2)HashSet:如何保证元素唯一性的呢? 通过元素的两个方法:hashCode(),equals();
判断元素是否相同,先要判断元素的hashCode(注:hashCodea()返回值为int 型)值是否一致,
只有在该值一致的情况下,才会去判断equals()方法。
(3)复写hashCode()方法时,尽量依据元素的判断相同的条件来定义每一个元素的哈希值。
public int hashCode() {
reutrn name.hashCode()+age*36;//尽量保证哈希值唯一性。
}
10)LinkedHashSet:该子类基于哈希表又融入了链表。可以对Set集合进行增删提高效率。
LinkedHashSet可以按元素的添加顺序来访问集合里的元素。但仍然不允许集合元素重复。
11)TreeSet:数据结构是:二叉树。
1. 如何保证元素唯一性的呢? 通过比较方法的return 0来判断元素是否相同。
2. treeSet可以对Set集合中的元素进行排序。
3.添加的方法
Object first():返回集合中的第一个元素。
Object last():返回集合中的最后一个元素。
Object lower(Object e):返回集合中位于指定元素之前的元素(即小于指定元素的最大元素,参数元素不需要是TreeSet集合里的元素)。
Object higher(Object e):返回集合中位于指定元素之后的元素(即大于指定元素的最小元素,参数元素不需要是TreeSet集合里的元素)。
SortedSet subSet(formElement,toElement):返回次Set的子集合,范围从formElement(包含)到toElement(不包含)。
SortedSet headSet(toElement):返回此Set的子集,由小于toElement的元素组成。
SortedSet tailSet(fromElement):返回此Set的子集,由大于或等于fromElement的元素组成。
public class hjh {
public static void main(String[] args) {
TreeSet nums = new TreeSet();
nums.add(5);
nums.add(2);
nums.add(10);
nums.add(-9);
System.out.println(nums);
System.out.println(nums.first());
System.out.println(nums.last());
System.out.println(nums.headSet(4)); // 不包含4
System.out.println(nums.tailSet(5)); // 包含5
System.out.println(nums.subSet(-3, 4));
}
}
/*
[-9, 2, 5, 10]
-9
10
[-9, 2]
[5, 10]
[2]*/
4. 排序的两种方式:
一,让元素自身具备比较性。也就是元素需要实现Comparable接口,覆盖compareTo方法。
这种方式也作为元素的自然排序,也可称为默认排序。
二,让容器自身具备比较性,自定义比较器。
需求:当元素自身不具备比较性,或者元素自身具备的比较性不是所需的。
那么这时只能让容器自身具备。 定义一个类实现Comparator接口,覆盖compare方法。
并将该接口的子类对象作为参数传递给TreeSet集合的构造函数。
当Comparable比较方式,及Comparator比较方式同时存在,以Comparator比较方式为主。
5. 注意:在覆盖compareTo方法,或者compare方法时,必须要明确比较的主要条件相等时,需要参阅次要条件。
//第一种:元素(类)本身就具有比较方法。
class Person implements Comparable {
private int age;
private Object name;
public int compareTo(Object obj) {
Person p = (Person) obj;
if (this.age > p.age)
return -1;
if (this.age < p.age)
return 1;
return ((Person) this.name).compareTo(p.name);
}
}
//第二种方法:建立一个新的类继承Comparator接口,并覆盖compare(Object o1,Object o2)方法。
class MyCompare implements Comparator {
public int compare(Object o1,Object o2) {
Permission p1 = (Permission)o1;
Permission p2 = (Permission)o2;
if(p1.getAge()>p2.getAge())
return 1;
if(p1.getAge()<p2.getAge())
return -1;
return 0;
}
}
{
TreeSet ts = new TreeSet(new MyCompare());
}
}
//第二种方法也可以采用匿名内部类的方法
TreeSet ts = new TreeSet(new Comparator() {
public int compare(Object o1,Object o2) {
String s1 = (String)o1;
String s2 = (String)o2;
if(s1.length()>s2.length())
return 1;
if(s1.length()<s2.length())
return -1;
return s1.compareTo(s2);
}
});
12) 技巧:
如何判断这些容器的数据结构?
通过每一个容器的名称即可明确其数据结构:
ArrayList: 数组 array。
LinkedList: 链表:link。
HashSet: 哈希表:hash。
TreeSet: 二叉树:tree。
HashMap: 哈希表。hash。
TreeMap: 二叉树。tree。
看到array,就要想到角标。
看到link,就要想到first,last。
看到hash,就要想到hashCode,equals.
看到tree,就要想到两个接口。Comparable,Comparator。
class R {
int count;
public R(int count){
this.count = count;
}
public String toString() {
return "R[count:" + count;
}
public boolean equals(Object obj){
if(this == obj)
return true;
if(obj != null && obj.getClass() == R.class){
R r = (R)obj;
if(r.count == this.count){
return true;
}
}
return false;
}
public int hashCode(){
return this.count;
}
}
public class dfsa {
public static void main(String[] args) {
HashSet hs = new HashSet();
hs.add(new R(5));
hs.add(new R(-3));
hs.add(new R(9));
hs.add(new R(-2));
System.out.println(hs);
Iterator it = hs.iterator();
R first = (R)it.next();
first.count = -3;
System.out.println(hs);
hs.remove(new R(-3));
System.out.println(hs);
System.out.println("hs是否包含count为-3的R对象?" + hs.contains(new R(-3)));
System.out.println("hs是否包含count为5的R对象?" + hs.contains(new R(5)));
}
}
/*[R[count:-3, R[count:9, R[count:-2]
hs是否包含count为-3的R对象?false
hs是否包含count为5的R对象?false*/
注意: 当向HashSet中添加对象时,如果修改HashSet集合中的对象,有可能导致该对象与集合中的其他对象相等,从而导致HashSet无法准确访问该对象。
13)EnumSet类
EnumSet是一个专为枚举类设计的集合类,其中的所有元素都必须是指定枚举类型的枚举值。
EnumSet类没有暴露任何构造器来创建该类的实例,程序应该通过它提供的static方法来创建EnumSet对象。
public class dsf {
//目前个人使用量几乎为零,很少使用
//其使用方式和普通的Set没有区别,只是构造方法有一些特殊的而已。
public static void main(String[] args) {
// 创建一个指定类型的空的集合
EnumSet<MyEnum> set = EnumSet.noneOf(MyEnum.class);
set.add(MyEnum.RED);
set.add(MyEnum.GREEN);
set.add(MyEnum.BLUR);
showSet(set);
// 创建指定类型的所有数据的集合
EnumSet<MyEnum> set2 = EnumSet.allOf(MyEnum.class);
showSet(set2);
// 创建指定类型指定初始数据的集合
EnumSet<MyEnum> set3 = EnumSet.of(MyEnum.GREEN, MyEnum.RED,
MyEnum.WHITE);
showSet(set3);
// 创建指定类型,指定范围的集合
// 包含边界数据
EnumSet<MyEnum> set4 = EnumSet.range(MyEnum.RED, MyEnum.YELLOW);
showSet(set4);
// 集合的用法和普通的没有区别
}
/**
*显示Set里面的数据。
*/
private static void showSet(Set set) {
System.out.println(Arrays.toString(set.toArray()));
}
}
enum MyEnum {
BLACK, WHITE, RED, BLUR, GREEN, YELLOW
}
13)总结:Set 成员不 能重复
1)【HashSet】 外部无序地遍历成员。 成员可为任意Object子类 的对象,但如果覆盖了equals方法,同时注意修改hashCode方法。
2)【TreeSet】 外部有序地遍历成员; 附加实现了SortedSet, 支持子集等要求顺序的操作
成员要求实现Comparable接口,或者使用Comparator构造TreeSet。成员一般为 同一类型。
3)【LinkedHashSet】 按外部成员的插入顺序遍历成员 ,成员与HashSet成员类似。 在更多情况下,会使用 HashSet 存储重复自由的集合。
同时LinkedHashSet也是采用了Hash算法的方式进行存取对象元素的。所以添加到 LinkedHashSet 的对象对应的类也需要采用恰当方式来实现 hashCode() 方法。
4)EnumSet是所有Set实现类中性能最好的,但它只能保存同一个枚举类的枚举值作为集合元素。
14)List 集合:按添入顺序排序,允许重复。
1.继承Collection的方法,并添加了新的方法
|——List:有序,可以重复,有角标。
|——Set:无序,不可以重复。
————————————————————————————————————
List:中特有的方法。可以操作角标
1,添加(插入):add(index,obj)
2,删除:remove(index);
3,获取:get(index);
4,索引:indexOf(obj); lastIndexOf(obj);
5,取子列表:subList(start,end);
6,修改:set(index,obj);
7,list集合支持列表迭代器ListIterator:
8,Iterator在迭代时,只能对元素进行获取(next())和删除(remove())的操作。
9,对于Iterator的子接口ListIterator在迭代list集合时,还可以对元素进行添加(add(obj)),修改set(obj)的操作。
15)List:实现了所有可选列表操作,并允许包括 null 在内的所有元素
|--Vector: 底层是数组数据结构,线程是同步的,现的ArrayList替代,因为效率低。
| Vector:支持枚举取值,枚举和迭代器的功能是一致的。因为其功能方法名称过长,被迭代器取代。
|--ArrayList:底层是数组数据结构,线程是不同步的。查询的速度快。
|--LinkedList:底层是链表数据结构,线程是不同步的。增删的速度很快。
可以使用该集合去模拟出队列(先进先出) 或者堆栈(后进先出) 数据结构。
16) ArrayList
a)ArrayList底层采用数组实现,当使用不带参数的构造方法生成ArrayList对象时,实际上会在底层生成一个长度为10的Object类型数组。
b)使用ArrayList.add()方法增加元素,如果增加的元素个数超过10个,那么ArrayList底层会新生成一个数组,长度为原数组的1.5倍+1,然后将原数组的内容复制到新数组当中,并且后续增加的内容都会放到新数组当中。当新数组无法容纳增加的元素时,重复该过程。
c)对于ArrayList元素的删除操作,需要将被删除元素的后续元素向前移动,代价高。
public class ArrayListAdd {
public static void main(String[] args) {
List list = new ArrayList();
show(list);
}
public static void show(List list) {
// 添加元素
list.add("abc1");
list.add("abc2");
list.add("abc3");
System.out.println(list);
// 插入元素。
list.add(1,"abc9");
// 删除元素。
System.out.println("remove:"+list.remove(2));
// 修改元素。
System.out.println("set:"+list.set(1, "abc8"));
// 获取元素。
System.out.println("get:"+list.get(0));
// 获取子列表。
System.out.println("sublist:"+list.subList(1, 2));
System.out.println(list);
}
}
17) LinkedList
1. 底层是链表数据结构,线程是不同步的。增删的速度很快。
2. 可以使用该集合去模拟出队列(先进先出) 或者堆栈(后进先出) 数据结构。
3. 通过对自然封装该列表的对象进行同步操作
List list = Collections.synchronizedList(new LinkedList(...));
1.LinkedList:特有的方法。
addFirst(): -->jdk1.6 offerFirst(); 在开头插入指定的元素。
addLast(): -->jdk1.6 offerLast(); 在末尾插入指定的元素
getFirst(); -->jdk1.6 peekFirst(); 获取但不移除此列表的头
getLast(): -->jdk1.6 peekLast(); 获取但不移除此最后一个元素;
如果此列表为空,则返回 null。
removeFirst(): -->jdk1.6 pollFirst(); 获取并移除此列表的头
removeLast(): -->jdk1.6 pollFirst(); 获取并移除最后一个元素;
如果此列表为空,则返回 null。
* 请使用LinkedList来模拟一个堆栈或者队列数据结构。
* 堆栈:先进后出 First In Last Out FILO
public class Demo___LinkedList {
public static void main(String[] args){
LinkedList <String> linked=new LinkedList <String> ();
linked.add("a");
linked.add("b");
linked.add("c");
String st[]=linked.toArray(new String[]{});//指定的泛型类型
for(int i=linked.size()-1;i>0;i--){
System.out.print(st[i]+" ");
}
}
* 队列:先进先出 First In First Out FIFO
public class Demo__LinkedList{
public static void main(String[] args){
LinkedList <String> linked=new LinkedList <String> ();
linked.add("a");
linked.add("b");
linked.add("c");
for (String word : linked) {
System.out.println(word);
}
}
}
18) Vector
1. 底层是数组数据结构,线程是同步的,现的ArrayList替代,因为效率低。
2. Vector:支持枚举取值,枚举和迭代器的功能是一致的。因为其功能方法名称过长.被迭代器取代。
3. Vector 的大小可变的,以适应创建 Vector 后进行添加或移除项的操作。
4. 当一个Iterator被创建而且正在被使用,另一个线程改变了Vector的状态(例如,添加或删除了一些元素),
这时调用Iterator的方法时将抛出ConcurrentModificationException,因此必须捕获该异常。
Stack 类
Stack继承自Vector,实现一个后进先出的堆栈。
Stack提供5个额外的方法使得Vector得以被当作堆栈使用。
基本的push和pop方法,还有peek方法得到栈顶的元素,empty方法测试堆栈是否为空,search方法检测一个元素在堆栈中的位置。
Stack刚创建后是空栈。不建议使用
//后进先出
public static void main(String[] args){
//实例化
Stack <String> s=new Stack <String>();
//入栈
s.push("a");
s.push("b");
s.push("c");
//出栈,先进后出
System.out.println(s.pop()+" ");
System.out.println(s.pop()+" ");
System.out.println(s.pop()+" ");
}
}
19)ArrayList与LinkedList的比较分析:
1)ArrayList底层采用数组实现,LinkedList底层采用双向链表实现。
2)如果元素的数目超出了内部数组目前的长度它们都需要扩展内部数组的长度,
Vector缺省情况下自动增长原来一倍的数组长度,ArrayList是原来的50%,
3)当执行插入或删除操作时,采用LinkedList比较好。
当执行搜索操作时,采用ArrayList比较好。
当向ArrayList添加一个对象时,实际上是将该对象放置到了ArrayList底层所维护的数组当中;
当向LinkedList中添加一个对象时,实际上LinkedList内部会生成一个Entry对象,该Entry对象的结构为:
Entry {
Entry previous;
Object element;
Entry next;
}
其中的Object类型的元素element就是我们向LinkedList中所添加的元素,
然后Entry又构造好了向前与向后的引用previous、next,最后将生成的这个Entry对象加入到了链表当中。
换句话说,LinkedList中所维护的是一个个Entry对象。
3)浅谈数组链表与指针链表
数组链表访问快,复杂度O(1),但是添加删除慢,复杂度O(n);
指针链表访问慢,复杂度是O(n),但是添加删除快,复杂度O(1);
20)List 总结:允许重复项的有序集合
List 按存入顺序排放,元素可重复。
1.【ArrayList】: 元素单个,不同步,效率高,多用于查询,ArrayList是实现了基于动态数组的数据结构
2.【Vector】: 元素单个,同步线程安全,多用于查询,(实现动态数组)
Stack(实现堆栈)不安全。不建议使用
3.【LinkedList】:元素单个,多用于插入和删除,LinkedList基于链表的数据结构。
21)ListIterator
ListIterator 接口继承 Iterator 接口以支持添加或更改底层集合中的元素,还支持双向访问。
public class ListIteratorTest {
public static void main(String[] args) {
//实例化ArrayList接口
List list = new ArrayList();
//加入元素
list.add("aaa");
list.add("bbb");
list.add("ccc");
list.add("ddd");
System.out.println("下标0开始:" + list.get(1));
//取当前光标的元素
System.out.println("下标0开始:" + list.listIterator(1).next());
//取当前光标的元素
System.out.println("下标0开始:" + list.listIterator(2).next());
//取当前光标的元素
System.out.println("子List 1-3:" + list.subList(1, 3));
// 子列表包括1,不包括3
ListIterator it = list.listIterator();
// 默认从下标0开始,实例化ListIterator接口
// 隐式光标属性add操作 ,插入到当前的下标的前面
it.add("sss");
System.out.println(it.nextIndex());
//取下一元素下标
System.out.println(it.previous());
//取上一个元素
while (it.hasNext()) {
//使用hasNext()检查序列中是否元素
System.out.println("next Index=" + it.nextIndex() + ",Object="
+ it.next());
}// set属性
ListIterator it1 = list.listIterator();
//实例化ListIterator接口
it1.next();
it1.set("ooo");
//默认从下标0开始
//将下标赋给迭代器,迭代输出
ListIterator it2 = list.listIterator(list.size());// 下标
while (it2.hasPrevious()) {
//判断下标上一个
System.out.println("previous Index=" + it2.previousIndex()
+ ",Object=" + it2.previous());
}
}
}
/*下标0开始:bbb
下标0开始:bbb
下标0开始:ccc
子List 1-3:[bbb, ccc]
1
sss
next Index=0,Object=sss
next Index=1,Object=aaa
next Index=2,Object=bbb
next Index=3,Object=ccc
next Index=4,Object=ddd
previous Index=4,Object=ddd
previous Index=3,Object=ccc
previous Index=2,Object=bbb
previous Index=1,Object=aaa
previous Index=0,Object=ooo
*/
21)Map<K,V>从不重复的键到值的映射。
方法:
Map:一次存入一对元素,以键值对(Key,Value)形式存在,必须保证键的唯一性。
1,添加: put(K key,V value):返回的是被覆盖的Value,如果键没有重复,返回的是null。
2,删除: remove(key);
clear();
3,获取:value get(key); 也可以用于判断键是否存在的情况。当指定的键不存在的时候,返回的是null。
对于HashMap集合,可以存入null键null值。 。
4,判断: boolean containsKey(key);
boolean containsValue(value);
boolean isEmpty();
5,长度:int size();
6,取出:
将map集合转成Set集合后,在通过迭代器取出。
Set<k> keySet():将map集合中所有的键取出存入set集合。再通过get方法获取键对应的值。
Set<Map.Entry<k,v>> entrySet():将map集合中的键值映射关系打包成一个对象Map.Entry对象。
将该对象存入set集合。取出是可以通过Map.Entry对象的getKey,getValue获取 其键和值。
7,获取所有的值。 Collection<v> values();
22)Map结构
1,Map:
|--Hashtable:底层是哈希表数据结构,线程是同步的,不可以存入null键,null值。效率较低,被HashMap替代。
| 要保证键的唯一性,需要覆盖hashCode方法,和equals方法。
|
|--HashMap:最常用 底层是哈希表数据结构,线程是不同步的,可以存入null键,null值。
| | 要保证键的唯一性,需要覆盖hashCode方法,和equals方法。
| |
| |_____LinkedHashMap增删用基于hash表和双向链表实现。按存入顺序排序。可以Map集合进行增删提高效率。
|--TreeMap:排序用底层是二叉树数据结构。可以对map集合中的键进行排序。
| 需要使用Comparable或者Comparator进行比较排序。return 0,来判断键的唯一性。
|--WeakHashMap是一种改进的HashMap,它对key实行“弱引用”,如果一个key不再被外部所引用,那么该key可以被GC回收
|--IdentityHashMap比较键(和值)时使用引用相等性代替对象相等性。当且仅当 (k1==k2) 时,才认为两个键 k1 和 k2 相等
其实set集合,底层使用的就是map集合。
注意:Map集合中有一个特殊的对象是可以和IO对象相结合的:Properties。它是Hashtable的子类。
该集合对象不存在泛型,键和值都是字符串。
什么时候使用map集合?当对象之间存在着映射关系时,就要先想到map集合。
//Properties文件操作
public class PropertiesDemo4 {
public static void main(String[] args){
Properties pro=new Properties();
//设置内容
pro.setProperty("bj","北京" );
pro.setProperty("tj","天津" );
pro.setProperty("sh","上海" );
//设置文件的保存路径
File file=new File("d:"+File.separator+"area.xml");
try{
//保存属性到文件中,并设置注释内容
pro.storeToXML(new FileOutputStream(file), "Area Info");
}catch(Exception e){
e.printStackTrace();
}
try{
//读取文件属性
pro.loadFromXML(new FileInputStream(file));
}catch(Exception e){
e.printStackTrace();
}
System.out.println("1--bj属性存在 ,内容为"+pro.getProperty("bj"));
System.out.println("1--bj属性存在 "+pro.getProperty("bj"));
System.out.println("2--sc属性存在 "+pro.getProperty("sc"));
System.out.println("3--sc属性存在,同时设置显示的默认值 "+pro.getProperty("sc","没有发现"));
}
}
//HashMap一个键对应一个集合。
public class ManyMap {
public static void main(String[] args) {
// 这是一个一对多的映射,就是一个学样对应多个班级,一个班级又对应多个学生
Map<String, List<Student>> sname = new HashMap<String, List<Student>>();
// 定义学校,里面有班级和学生集合的映射,一个班级对应一个学生集合
List<Student> cname1 = new ArrayList<Student>();
List<Student> cname2 = new ArrayList<Student>();
// 定义两个学生类,也就是两个班级里的人数
sname.put("清华大学", cname1);
sname.put("清华大学", cname2);
cname1.add(new Student("001", "boy"));
cname1.add(new Student("002", "girl"));
cname1.add(new Student("003", "xiaozhang"));
cname2.add(new Student("001", "xiaoli"));
cname2.add(new Student("002", "hujintao"));
cname2.add(new Student("003", "wenjiabao"));
Set<Map.Entry<String, List<Student>>> entrykey = sname.entrySet();
for (Iterator<Map.Entry<String, List<Student>>> it = entrykey.iterator(); it.hasNext();) {
Map.Entry<String, List<Student>> item = it.next();
System.out.println("班级:" + item.getKey());
List<Student> stu = item.getValue();
for(Iterator<Student>iterator=stu.iterator();it.hasNext();) {
System.out.println(it.next()); }
show(stu);
}
}
public static void show(List<?> list) {
for (Iterator<?> it = list.iterator(); it.hasNext();) {
System.out.println(it.next());
}
}
}
//TreeMap 取子集
public class Demo___TreeMap {
public static void main(String [] args){
SortedMap <String,String> map=new TreeMap<String,String> ();
map.put("a", "aaa1");
map.put("d", "bbb2");
map.put("c", "aaaa10");
map.put("b", "bbbb11");
System.out.println(map);
System.out.println("第一个元素内容的key:"+map.firstKey());
System.out.println("-->所对应的value"+map.get(map.firstKey()));
System.out.println("最后一个对应的key:"+map.lastKey());
System.out.println("-->所对应的value"+map.get(map.lastKey()));
System.out.println("返回小于c指定范围的集合:");
for(Map.Entry<String, String> me:map.headMap("c").entrySet()){
System.out.println("\t|--"+me.getKey()+"-->"+me.getValue());
}
System.out.println("返回大于c指定范围的集合:");
for(Map.Entry<String, String> me:map.tailMap("c").entrySet()){
System.out.println("\t|--"+me.getKey()+"-->"+me.getValue());
}
System.out.println("部分集合:b--->d");
for(Map.Entry<String, String> me:map.subMap("b", "d").entrySet()){
System.out.println("\t|--"+me.getKey()+"-->"+me.getValue());
}
}
}
/**weakmap 弱引用
* 弱引用类即集合不使用就会自动清理,weakmap是弱引用类
* 强引用类,即内存不足时,JVM出现outofMemeryError也不会回收数据,map其他子类都是
* 软引用 :即内存不足时,JVM会回收数据
* 虚引用:和没有任何引用一样
*/
public class Demo__WeakHashmap {
public static void main(String[] args){
//实例化Map对象
Map <String,String> map=new WeakHashMap <String,String> ();
map.put(new String("10"), new String("aaa1"));
map.put(new String("18"), new String("ab1"));
map.put(new String("14"), new String("aca1"));
//进行垃圾回收
System.gc();
//map.put(new String("56"), new String("ar1"));
System.out.println(map);
}
}
集合框架中的工具类:特点:该工具类中的方法都是静态的。
Collections:常见方法:
1,对list进行二分查找:前提该集合一定要有序。
int binarySearch(list,key);//要求list集合中的元素都是Comparable的子类。
int binarySearch(list,key,Comparator);
2,对list集合进行排序。
sort(list);
sort(list,comaprator);
3,对集合去最大值或者最小值。
max(Collection)
max(Collection,comparator)
min(Collection)
min(Collection,comparator)
4,对list集合进行反转。 reverse(list);
5,对比较方式进行强行逆转。
Comparator reverseOrder();
Comparator reverseOrder(Comparator);
6,对list集合中的元素进行位置的置换。 swap(list,x,y);
7,对list集合进行元素的替换。如果被替换的元素不存在,那么原集合不变。 replaceAll(list,old,new);
8,可以将不同步的集合变成同步的集合。
Set synchronizedSet(Set<T> s)
Map synchronizedMap(Map<K,V> m)
List synchronizedList(List<T> list)
Arrays:用于对数组操作的工具类。
1,binarySearch(int[])
binarySearch(double[])……
2,sort(int[])
sort(char[])……
3,toString(int[]).....:将数组变成字符串。
4,copyOf();复制数组。
5,copyOfRange():复制部分数组。
6,equals(int[],int[]);比较两个数组是否相同。
7,List asList(T[]);将数组变成集合。
这样可以通过集合的操作来操作数组中元素,但是不可以使用增删方法,add,remove。
因为数组长度是固定的,会出现UnsupportOperationExcetion。
可以使用的方法:contains,indexOf。。。 如
果数组中存入的基本数据类型,那么asList会将数组实体作为集合中的元素。
如果数组中的存入的应用数据类型,那么asList会将数组中的元素作为集合中的元素。
如果想要将集合变数组: 可以使用Collection中的toArray方法。
传入指定的类型数组即可,该数组的长度最好为集合的size。
五个最常用的集合类
1.ArrayList: 元素单个,效率高,多用于查询
2.Vector: 元素单个,线程安全,多用于查询
3.LinkedList:元素单个,多用于插入和删除
4.HashMap: 元素成对,元素可为空
5.HashTable: 元素成对,线程安全,元素不可为空
Map集合与Collection集合的区别:
1. Map中一次存储是键值对。
Collection中一次存储是单个元素。
2,Map的存储使用的put方法。
Collection存储使用的是add方法。
3,Map的取出,是讲Map转成Set,在使用迭代器取出。
Collection取出,使用就是迭代器。
4,如果对象很多,必须使用容器存储。
如果元素存在着映射关系,可以优先考虑使用Map存储或者用数组,
如果没有映射关系,可以使用Collection存储。
排序依据:
类 排序
BigDecimal, BigInteger, Byte, Double, Float,
Integer, Long, Short 按数字大小排序
Character 按 Unicode 值的数字大小排序
CollationKey 按语言环境敏感的字符串排序
Date 按年代排序
File 按系统特定的路径名的全限定字符的 Unicode 值排序
ObjectStreamField 按名字中字符的 Unicode 值排序
String 按字符串中字符 Unicode 值排序
------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培
训、.Net培训</a>、期待与您交流! -------