java.util包中提供了一些集合类,我们把这些集合又称之为容器。
容器与数组的区别:1.数组的长度是固定的 ,而容器的长度是可变的
2.数组用来存放一些基本数据类型,而容器用来存放对象的引用。
List:有序可重复的集合。
List接口的常用实现类有ArrayList 和LinkedList.
ArrayList:它的底层实现了可变的数组,允许保存所有的元素,包括null;并可以根据索引 的位置快速的随机访问,缺点是向指定的索引位置插入对象(add(int index,element))或者删除对象(remove())的速度比较慢。
LinkedList:它的底层实现是链表结构。这种结构的优点 是便于向集合中插入和删除对象,需要访问集合中的元素,LinkedList类实现的效率较低。
补充:(数组中插入、删除数据项时,需要移动其它数据项,非常繁琐。链表是根据next指针找到下一个元素,方便插入和删除)
从内存存储来看
1. (静态)数组从栈中分配空间, 对于程序员方便快速,但是*度小
2. 链表从堆中分配空间, *度大但是申请管理比较麻烦
List的一些常用方法:可自行查询javaAPI文档
package CollectionDemo;Set: 无序不可重复的集合
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* Collection的List集合的常用方法测试
* @author Anota
*/
public class Demo {
public static void main(String[] args) {
List<Student> list=new ArrayList<Student>();
Student stu=new Student("张三",001,1);
Student stu1=new Student("李四",002,1);
Student stu2=new Student("王五",003,1);
Student stu3=new Student("赵六",004,1);
//判断容器是否为空 -->isEmpty() 空返回true
boolean flag=list.isEmpty();
System.out.println(flag);
//向容器里添加element-->add()
list.add(stu);
list.add(stu1);
list.add(stu2);
list.add(stu3);
System.out.println(list.size());//打印容器的大小
//插入元素到指定的位置-->add(String item, int index)可自行查API文档
//移除指定的元素-->remove(int index) removeall()移除所有的容器元素
list.remove(0);
System.out.println(list.size());
//返回指定索引的元素-->get(int index)
Student s=list.get(2);
System.out.println(s);
System.out.println("=======================");
//用指定的元素代替指定位置的元素
list.set(0, stu2);
//容器的遍历 3种 方法-->1.普通for循环 2.foreach 3.迭代器Iterator
for(Student student:list){
System.out.println(student);
}
System.out.println("=======================");
Iterator it=list.iterator();
while(it.hasNext()){ //判断元素是否还有
System.out.println(it.next());//返回下一个元素
}
//将list以一定顺序的形式返回 -->to Array()
Object obj[]=list.toArray();
}
}
Set接口常用的实现类有:HashSet 和TreeSet
HashSet:由哈希表(实际是一个HashMap实例)支持,它不保证Set的迭代顺序。此类允许使用null;但最多一个(不重复)。(性能好)
TreeSet:(基于TreeMap)不仅实现了Set接口,还实现了java.util.SortedSet接口,因此。TreeSet类实现的Set集合在遍历集合时按照自然顺序递增排列,也可以按照指定的比较器排列(排序方法)即i,可以通过比较器对用TreeSet类实现的Set集合中的对象进行排序。(存入TreeSet 的集合必须实现Comparable接口,重写它的comparaTo()比较此对象喻指定对象的顺序。如果大于、等于、小于,分别返回1,0,-1)
package CollectionDemo;Set其他对应的方法和ArrayList差不多。
/**
* TreeSet 的简单应用
*/
import java.util.Iterator;
import java.util.TreeSet;
public class StudentDemo implements Comparable {
private String name;
private int id;
public StudentDemo() {
}
public StudentDemo(String name, int id) {
super();
this.name = name;
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Override
public int compareTo(Object o) {
StudentDemo stu=(StudentDemo) o;
int result=id>stu.id?1:(id==stu.id?0:-1);
return result;
}
public static void main(String[] args) {
StudentDemo s=new StudentDemo("张三",01011);
StudentDemo s1=new StudentDemo("李四",01021);
StudentDemo s2=new StudentDemo("王五",01051);
StudentDemo s3=new StudentDemo("赵六",01012);
TreeSet<StudentDemo> tree=new TreeSet<StudentDemo>();
tree.add(s);
tree.add(s1);
tree.add(s2);
tree.add(s3);
System.out.println(tree.size());
Iterator<StudentDemo> it=tree.iterator();
while(it.hasNext()){
StudentDemo student =it.next();
System.out.println(student.getId()+"-->"+student.getName());
}
}
}
Map:Map集合没有继承Collection接口,其提供了键对值得映射操作。每个键只能映射一个value,键不能重复,所以键只能有一个null,而value可以有多个null。它的底层实现是(数组+链表)的结构。它重写了Object类的hashcode()和equals()。
注意此处hashcode()和equals():如果两个对象equals ,对应的hashcode相等,但是如果两个对象那个不equals,hashcode也可能相等。hashcode不相等,则一定不equals。
我们可以把Map这个接口方法分成三组操作:改变、查询和提供可选视图
HashMap 类和 TreeMap 类
“集合框架”提供两种常规的 Map
实现:HashMap
和TreeMap
。和所有的具体实现一样,使用哪种实现取决于您的特定需要。在Map
中插入、删除和定位元素,HashMap
是最好的选择。但如果您要按顺序遍历键,那么TreeMap
会更好。根据集合大小,先把元素添加到 HashMap
,再把这种映射转换成一个用于有序键遍历的 TreeMap
可能更快。使用HashMap
要求添加的键类明确定义了 hashCode()
实现。有了TreeMap
实现,添加到映射的元素一定是可排序的。TreeMap不允许键对象有null。
为了优化 HashMap
空间的使用,您可以调优初始容量和负载因子。这个TreeMap
没有调优选项,因为该树总处于平衡状态。
package CollectionDemo;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* HashMap常用的方法
* @author Anota
*/
public class HashMapDemo {
//javabean省略
public static void main(String[] args) {
Map<String,Student> map=new HashMap<String,Student>();
//添加键值对-->put()
map.put("1班学生成绩", new Student("张三",2014001,1));
map.put("2班学生成绩", new Student("李四三",2014138,38));
map.put("3班学生成绩", new Student("王五",2014212,12));
//通过键得到值-->get(键)
map.get("1班学生成绩");
//将键转化成Set视图 -->keyset()
Set set=map.keySet();
//遍历键
Iterator<String> it=set.iterator();
while(it.hasNext()){
String str=it.next();
//打印map集合
System.out.print(str);
System.out.println(map.get(str).getName()+"-->"+map.get(str).getId()+"-->"+map.get(str).getNo());
}
//移除
map.remove("1班学生成绩");
System.out.println(map.size());
}
}
拓展;关于Hashmap和Hashhtable的区别:
1.HashMap是非线程安全的 效率相对较高,而Hashtable是线程安全的 ,效率相对较低。
2.HashMap的父类是AbstractMap,Hashtable的父类是Dictionary.
3.HashMap的键最对只能有一个null,值可以有多个null;Hashtable的键和值不能为null。
Hashtable 的最常用的子类是propertise(读取资源配置文件的类,最后有介绍)。
collections类:
同Arrays类(Array的操作类)的作用类似,是Collectionj接口的“包装器”,即定义了一些对Collection的操作,包括二分查找和排序(sort())等,同时定义了将集合转为线程安全的方法。
注意:如果想要对一个集合进行排序,你可以使用collections.sort(List list)方法,或者选用TreeSet、TreeMap.
Properties类用法
在项目中经常遇到将配置信息按键值对的格式保存到文件中,然后使用Properties类将文件的内容读入内存,获取配置信息。
和Map相比,Properties具有如下特点:
1.能从输入流(如文件)中获取键值对信息。
2.能将键值对信息保存到输出流中(如文件)。
该实例实现了向Properties类中添加键值对,从Properties类中取出某个键的值,把整个Properties对象保存到文件中,以及将文件中的键值对信息直接加载到Properties对象中。
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
public class TestProperties {
public static void main(String[] args) throws IOException {
//新建一个Properties对象
Properties props = new Properties();
//往Properties中存放数据,格式位
//key 和 value都是字符串
props.setProperty("name", "ZhangSan");
props.setProperty("gender", "male");
props.setProperty("age", "30");
props.setProperty("telNO", "01088888888");
props.setProperty("address", "xxxxxxxx");
//从Properties中获取数据。必须提供key
System.out.println("name: " + props.getProperty("name"));
System.out.println("gender: " + props.getProperty("gender"));
System.out.println("age: " + props.getProperty("age"));
System.out.println("telNO: " + props.getProperty("telNO"));
System.out.println("address: " + props.getProperty("address"));
//可以位返回值提供一个缺省值,当Properties中没有该key时,用默认值返回
System.out.println("other: " + props.getProperty("other", "none"));
//将Properties中的数据保存到输出流,比如文件输出流
String fileName = "c:/test.properties";
FileOutputStream out = new FileOutputStream(fileName);
props.store(out, "test");
out.close();
//打开c:/test.properties文件,可以看见里面的内容,注意到,顺序是改变了的。
Properties newProps = new Properties();
newProps.setProperty("type", "newProps");
//可以从输入流中获取加载数据,比如文件输入流
//从properties文件中加载数据
FileInputStream in = new FileInputStream(fileName);
newProps.load(in);
in.close();
System.out.println();
System.out.println("type: " + newProps.getProperty("type"));
System.out.println("name: " + newProps.getProperty("name"));
System.out.println("gender: " + newProps.getProperty("gender"));
//将Properties中的数据输出到一个输出流
System.out.println();
props.list(System.out);
}
}
}