类集框架接口的具体特点
接口的继承关系
集合框架中的实现类
Collection接口
1. 此接口是单值存放的最大父类接口,可以向其中保存多个单值(单个的对象)数据,一般不直接使用,因为表示的操作意义不明确。
2. 使用了泛型的定义,在操作时必须指定具体的操作类型,以保证类集操作的安全性,避免发生ClassCastException异常
List接口
1. ArrayList:
public class ArrayListTest {
public static void main(String[] args) {
List list = new ArrayList();
list.add("Hello");
list.add("Hello");
list.add(1,"World");//在第1个位置(即第一个数据之后,以0——(size()-1)计数)
list.add(3,"Java");//在第3个位置添加
System.out.println(list);
System.out.println("集合中有多少数据:" + list.size());
System.out.println("集合中是否有Java:" + list.contains("Java"));//此处区分大小写
System.out.println("得到第几位的元素" + list.get(2));
System.out.println("Java字符串的位置:" + list.indexOf("Java"));
String[] strs = list.toArray(new String[] {});// 集合转指定类型的数组
for (Object str : strs) {
System.out.print(str + ", ");
}
System.out.println();
String[] arr = { "hello", "java", "hello", "jsp"};
List list1 = Arrays.asList(arr);//数组转列表(大小固定,为数组大小)
System.out.println("数组转列表:" + list1);
List subList=list.subList(1, 3);//返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图
System.out.println(subList);
Collection coll = new ArrayList<>();
coll.add("Hello");
coll.add("SQL");
list.addAll(coll);// 将coll集合中的所有元素添加至list
System.out.println("将coll集合中的所有元素添加至list:" + list);
System.out.println("list是否包含coll:" + list.containsAll(coll));
// list.removeAll(coll);//从list中删除两个集合的交集
// System.out.println("删除两个集合的交集后:" + list);//删除两个集合的交集后:[World, Java]
list.retainAll(coll);//保留交集,其余删除
System.out.println("保留交集,其余删除后:" + list);
list.remove("Hello");//删除'Hello'
System.out.println("删除'Hello'后:" + list);//只删除第一个
list.clear();
System.out.println("清空所有元素后:" + list);
System.out.println("集合是否为空:" + list.isEmpty());
}
}
//[Hello, World, Hello, Java]
//集合中有多少数据:4
//集合中是否有Java:true
//得到第几位的元素Hello
//Java字符串的位置:3
//Hello, World, Hello, Java,
//数组转列表:[hello, java, hello, jsp]
//[World, Hello]
//将coll集合中的所有元素添加至list:[Hello, World, Hello, Java, Hello, SQL]
//list是否包含coll:true
//保留交集,其余删除后:[Hello, Hello, Hello, SQL]
//删除'World'后:[Hello, Hello, SQL]
//清空所有元素后:[]
//集合是否为空:true
2. LinkedList:
public class LinkedListDemo {
public static void main(String[] args) {
LinkedList ll = new LinkedList();
ll.add("A");
ll.add("B");
ll.add("C");
System.out.println("初始化列表:" + ll);
ll.addFirst("X");//在链表的表头增加数据
ll.addLast("Y");//在链表的表尾增加数据
System.out.println("增加头和尾之后的链表:" + ll);
System.out.println("element找到的表头:" + ll.element());//element()表示获取但不移除此列表的头
System.out.println("element找完之后:" + ll);
System.out.println("peek找到的表头:" + ll.peek());//获取但不移除此列表的头(第一个元素)
System.out.println("peek找完之后:" + ll);
System.out.println("poll找到的表头:" + ll.poll());//获取并移除此列表的头(第一个元素)
System.out.println("poll找完之后:" + ll);
ll.offer("g");//将指定元素添加到此列表的末尾
System.out.println("添加指定元素之后的链表:" + ll);
Collections.fill(ll, "x");//使用指定元素替换指定列表中的所有元素
System.out.println("替换之后的链表:" + ll);
}
}
//初始化列表:[A, B, C]
//增加头和尾之后的链表:[X, A, B, C, Y]
//element找到的表头:X
//element找完之后:[X, A, B, C, Y]
//peek找到的表头:X
//peek找完之后:[X, A, B, C, Y]
//poll找到的表头:X
//poll找完之后:[A, B, C, Y]
//添加指定元素之后的链表:[A, B, C, Y, g]
//替换之后的链表:[x, x, x, x, x]
3. 区别:
1) 我们可以将ArrayList看作是能够自动增长容量的数组,可以直接利用ArrayList的toArray()返回一个数组
2) ArrayList底层采用数组完成,而LinkedList则是以一般的双向链表(double-linked list)完成,其内每个对象除了数据本身外,还有两个引用,分别指向前一个元素和后一个元素
3) LinkedList在实现List接口的同时,还实现了Queue接口,采用“先进先出”的方式操作
4) 如果我们经常在List的开始处增加元素,或者在List中进行插入和删除操作,我们应该使用LinkedList,否则的话,使用ArrayList将更加快速
Set接口
Set接口不能增加重复元素,实例无法像List接口那样可以进行双向输出。
1. HashSet:散列的存放:不能存放重复元素,并且采用散列的存储方式,无序排列
2. TreeSet:有序的存放:不能存放重复元素,有序排列,可以自定义类进行去重复并按照自己规定的顺序进行排序
3. TreeSet实现了SorteSet接口(是 SorteMap 的 set 对应接口)public class SetTest {
public static void main(String[] args) {
// hashSet
Set hashSet = new HashSet();
hashSet.add("A");
hashSet.add("A");
hashSet.add("B");
hashSet.add("C");
hashSet.add("C");
hashSet.add("D");
System.out.println("hashSet:" + hashSet);
// hashSet:[D, A, B, C]
// treeSet
Set treeSet = new TreeSet();
treeSet.add("D");
treeSet.add("A");
treeSet.add("C");
treeSet.add("D");
treeSet.add("B");
treeSet.add("A");
System.out.println("treeSet:" + treeSet);
// treeSet:[A, B, C, D]
// myTreeSet
Set myTreeSet = new TreeSet();
myTreeSet.add(new Child("张三", 18));
myTreeSet.add(new Child("李四", 20));
myTreeSet.add(new Child("王五", 21));
myTreeSet.add(new Child("王五", 21));
myTreeSet.add(new Child("张三", 19));
myTreeSet.add(new Child("张三", 18));
System.out.println("myTreeSet:" + myTreeSet);
// myTreeSet:[姓名:张三==年龄:18, 姓名:张三==年龄:19,
//姓名:李四==年龄:20, 姓名:王五==年龄:21]
// SortedSet
SortedSet sortedSet = new TreeSet();
sortedSet.add("A");
sortedSet.add("B");//同样不能放入重复
sortedSet.add("B");
sortedSet.add("C");
sortedSet.add("A");
sortedSet.add("D");
sortedSet.add("E");
System.out.println("第一个元素:" + sortedSet.first());//第一个元素:A
System.out.println("最后一个元素:" + sortedSet.last());//最后一个元素:E
System.out.println("headSet元素:" + sortedSet.headSet("C"));
//C的前面,不包括C headSet元素:[A, B]
System.out.println("tailSet元素:" + sortedSet.tailSet("C"));
//C的后面,包括 CtailSet元素:[C, D, E]
System.out.println("subSet元素:" + sortedSet.subSet("B", "D"));
//B、D中间,包含B不包含D subSet元素:[B, C]
}
}
class Child implements Comparable {
// TreeSet中为有序排列,所以对于自定义的类使用TreeSet进行存放时,
//对于一个对象必须指定好排序规则,需要实现Commparable接口才能正常使用
private String name;
private int age;
public Child(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "姓名:" + this.name + "==年龄:" + this.age;
}
@Override
public boolean equals(Object obj) {// 比较方法重载,用于进行比较两个对象,并去除重复对象
if (this == obj) {// 地址相等
return true;// 是同一个对象
}
if (this == null) {// 地址为空
if (obj != null)
return false;// 不是同一个对象
}
Child temp = (Child) obj;// 进行向下转型
if ((this.name.equals(temp.name)) && (this.age != temp.age)) {// 依次判断属性是否相等
return true;// 全部相等,是一个对象
} else {
return false;
}
}
@Override
public int hashCode() {// 对于重复的判断,只覆写equals方法不够,还需要覆写hashCode方法,
//利用指定的公式将类中全部属性进行计算,以求出一个不会重复的哈希码,从而判断不重复
return this.name.hashCode() * this.age;// 指定哈希码编写公式
}
@Override
public int compareTo(Child o) {
if (this == o) {// 地址相等
return 0;// 相等返回0,大于返回正数,小于返回负数
}
if (this == null) {// 地址为空
if (o != null)
return -1;
}
if (!this.name.equals(o.name)) {// 姓名不相等则按姓名排
return this.name.compareTo(o.name);// 按字典顺序比较两个字符串
}
// return o.age - this.age;// 年龄按从o到this的顺序排
return this.age - o.age;// 年龄按从this到o的顺序排
}
}
集合的输出
1. 迭代输出 Iterator(最常使用):是专门的迭代输出接口,由前向后单向输出。所谓的迭代输出接口就是将元素一个个进行判断,判断其是否有内容,如果有内容则把内容取走
2. 双向迭代输出Listlterator:可以实现由后向前或者由前向后的双向输出(只有List接口才可以实现),若想要后向前输出,必须先完成由前向后的输出
3. Foreach:增强型循环public class IteratorTest {
public static void main(String[] args) {
//Iterator代码
List list = new ArrayList<>();
list.add("Hello");
list.add("World");
list.add("Hello");
list.add("Java");
Iterator itr = list.iterator();//直接实例化Iterator接口
while (itr.hasNext()){// 是否有下一个数据
String str = itr.next();
if("Java".equals(str)){//判断内容里是否有“I”
itr.remove();//如果有就删除该元素
}
}
System.out.println("使用Iterator:" + list);
//ListIterator代码
System.out.println("========================");
List list1 = new ArrayList();
list1.add("Hello");
list1.add("World");
list1.add("Hello");
list1.add("Java");
ListIterator litr = list1.listIterator();
System.out.print("使用ListIterator由前向后输出:");
while (litr.hasNext()) {
String string = litr.next();
System.out.print(string + "、");
}
System.out.println();
System.out.print("使用ListIterator由后向前输出:");
while (litr.hasPrevious()) {
String string = litr.previous();
System.out.print(string + "、");
}
//Foreach代码
System.out.println();
System.out.println("=========================");
List list2 = new ArrayList();
list2.add("Hello");
list2.add("World");
list2.add("Hello");
list2.add("Java");
System.out.print("使用foreach输出:");
for (String str : list2) {
System.out.print(str + "、");
}
}
}
//使用Iterator:[Hello, World, Hello]
//========================
//使用ListIterator由前向后输出:Hello、World、Hello、Java、
//使用ListIterator由后向前输出:Java、Hello、World、Hello、
//=========================
//使用foreach输出:Hello、World、Hello、Java、
Map:
1. Map.Entry接口简介:是Map内部定义的一个接口,专门用来保存key→value的内容(实际上是将key→value的数据保存在Map.Entry的实例后,再在Map集合中插入一个个的Map.Entry的实例化对象)
2. HashMap:无序存放,新的操作类,key不允许重复
3. HashTable:无序存放,旧的操作类,key不允许重复(除了Hashtable可以同步和不允许使用null之外, Hashtable与HashMap类大致相同)
public class MapTest {
public static void main(String[] args) {
//HashMap代码
Map map = null;
map = new HashMap();
map.put("a", 97);
map.put("b", 98);
map.put("c", 99);
map.put("d", 100);
map.put(null, null);//HashMap允许放入null,而HashTable不可以
System.out.println(map);
map.put("a", 0);// 会将之前相同Key值的value值覆盖
System.out.println(map);
System.out.println("字母a的ASCII码:" + map.get("a"));//根据key值得到value值
System.out.println("有没有b的ASCII码:" + map.containsKey("b"));//查找指定的key是否存在
System.out.println("有没有ASCII码等于100的字母:" + map.containsValue(100));//查找指定的value是否存在
System.out.println("map是否为空:" + map.isEmpty());
System.out.println("map中有多少数据:" + map.size());
map.remove("d");
System.out.println("删掉d后,map中有多少数据:" + map.size());
System.out.println("===============================");
Set keys = map.keySet();//得到全部的key
System.out.print("全部的key:");
for (String k : keys) {//利用增强型循环输出
if("a".equals(k)){
map.put("a", 55);//利用put将a的值更改
}
System.out.print(k + "、");
}
System.out.println();
Collection values = map.values();//得到全部的value
Iterator itr1 = values.iterator();//利用Iterator进行输出
System.out.print("全部的value:");
while(itr1.hasNext()){
Integer string1 = itr1.next();
System.out.print(string1 + "、");
}
System.out.println();
System.out.println("================================");
map.clear();
System.out.println("清空操作后,map是否为空:" + map.isEmpty());
Map map1 = new HashMap<>();
map1.put("q", 7);
map1.put("w", 8);
map1.put("e", 9);
map.putAll(map1);//将map1的所有数据放入map中
System.out.println("放入map1后的map:" + map);
System.out.println("map1:" + map1);
System.out.println();
Set> entrys = map.entrySet();//可以同时得到key与value的值的列表
for (Map.Entry entry : entrys) {
System.out.println("key:" + entry.getKey() + " value:" + entry.getValue());
}
//TreeMap代码
System.out.println("============================");
Map treeMap = new TreeMap();
treeMap.put("C", "张三");
treeMap.put("A", "李四");
treeMap.put("B", "李四");
treeMap.put("A", "王五");
Set treeSet = treeMap.keySet();
Iterator treeItr = treeSet.iterator();
while(treeItr.hasNext()){
String treeStr = treeItr.next();
System.out.println(treeStr + "--->" + treeMap.get(treeStr));//取出key对应的key值
}
}
}
//{null=null, d=100, b=98, c=99, a=97}
//{null=null, d=100, b=98, c=99, a=0}
//字母a的ASCII码:0
//有没有b的ASCII码:true
//有没有ASCII码等于100的字母:true
//map是否为空:false
//map中有多少数据:5
//删掉d后,map中有多少数据:4
//===============================
//全部的key:null、b、c、a、
//全部的value:null、98、99、55、
//================================
//清空操作后,map是否为空:true
//放入map1后的map:{w=8, e=9, q=7}
//map1:{w=8, e=9, q=7}
//
//key:w value:8
//key:e value:9
//key:q value:7
//============================
//A--->王五
//B--->李四
//C--->张三
5. WeekHashMap:弱引用,之前的子类都是强引用保存,即里面的内容不管是否使用都始终在集合里,而WeekHashMap则当利用“System.gc()”进行垃圾收集时,集合会自动清理暂时不用的数据
6. Key可以重复的Map集合:IdentityHashMap
只要key地址不是相等的,就可以添加进去而不被覆盖
Map接口使用的注意事项
1. 不能直接使用迭代输出Map中的全部内容(Map一般很少直接输出,只是作为查询使用,而Collection接口一般用来传递内容和输出)
1) 使用Iterator输出(最标准的操作流程)
1> 将Map的实例通过entrySet方法变为Set接口对象
2> 通过Set接口实例化为Iterator实例化
3> 通过Iterator迭代输出,每个内容都是Map.Entry的对象
4> 通过Map.Entry进行key→value的分离Set treeSet = treeMap.keySet();
Iterator treeItr = treeSet.iterator();
while(treeItr.hasNext()){
String treeStr = treeItr.next();
System.out.println(treeStr + "--->" + treeMap.get(treeStr));
2) Foreach输出(将Map集合变为Set集合进行输出)
Set> entrys = map.entrySet();//可以同时得到key与value的值的列表
for (Map.Entry entry : entrys) {
System.out.println("key:" + entry.getKey() + " value:" + entry.getValue());
2. 直接使用非系统的类作为key
如果使用的自定义的类表示Map中的value,则按照格式完成即可,但是,如果要使用一个自定义的对象表示Map中的key,则对象所在的类中一定要覆写equals()和hashCode()方法,否则无法找到对应的value(类似于treeSet处,需要一一进行比较)
其他集合类
1. Stack类:栈,先进后出。
2. 属性类:Properties
public class PropertiesDemo {
public static void main(String[] args) {
Properties prop = new Properties();
prop.setProperty("system.language", "zh_CN");//设置属性
prop.setProperty("color", "red");
prop.setProperty("font", "黑体");
prop.setProperty("font.style", "bold");
System.out.println("配置的颜色"+prop.getProperty("color"));//根据key值取得属性的value,如果没有则返回null
System.out.println("字体样式"+prop.getProperty("style"));//未找到则返回null
String style = prop.getProperty("style","normal");
System.out.println("字体样式"+style);
prop.list(System.out);//将属性按列表输出到指定的输出流(此处为控制台)
try {
prop.store(new FileOutputStream("c:config.txt"), "系统配置");
//将prop中的配置保存到C盘中的config文件中,并设置注释内容
} catch (IOException e) {
e.printStackTrace();
}
}
}
//配置的颜色red
//字体样式null
//字体样式normal
//-- listing properties --
//font.style=bold
//color=red
//font=黑体
//system.language=zh_CN