-
3.2 TreeSet集合
-
- 总结
-
四、Queue结构的集合
-
五、Iterator(迭代器)
-
5.1 遍历集合
-
其他
主要分为:ArrayList类,LinkedList类,Vector类,Stack类
1.1 ArrayList类
无同步性,线程不安全
import java.util.*;//集合类基本上在util包中
public class Demo01 {
public static void main(String[] args) {
//定义ArrayList对象
ArrayList al=new ArrayList();
//显示大小
System.out.println(“al大小:”+al.size());
//向all中加入数据(类型是Object)
//创建一个职员
Clerk clerk1=new Clerk(“宋江”,50,1000);
Clerk clerk2=new Clerk(“吴用”,45,1200);
Clerk clerk3=new Clerk(“林冲”,35,1300);
//将clerk1加入到al中
al.add(clerk1);
al.add(clerk2);
al.add(clerk3);
//可不可以放入同样的对象?
al.add(clerk1);
//显示大小
System.out.println(“al大小:”+al.size());
//如何访问al中的对象(数据)
//访问第一个对象
//Clerk temp=(Clerk)al.get(0);
//System.out.println(“第一个人的名字是:”+temp.getName());
//遍历al所有的对象(数据)
for(int i=0;i<al.size();i++){
Clerk temp=(Clerk)al.get(i);
System.out.println(“名字:”+temp.getName());
}
//如何从al中删除一个对象
al.remove(1);
System.out.println(“=删除吴用=”);
//遍历al所有的对象(数据)
for(int i=0;i<al.size();i++){
Clerk temp=(Clerk)al.get(i);
System.out.println(“名字:”+temp.getName());
}
}
}
//定义一个员工类
class Clerk{
private String name;
private int age;
private float sal;
public Clerk(String name,int age,float sal){
this.name=name;
this.age=age;
this.sal=sal;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public float getSal() {
return sal;
}
public void setSal(float sal) {
this.sal = sal;
}
}
1.2 LinkedList集合类
//LinkedList集合类的使用
import java.util.*;
public class Demo02 {
public static void main(String[] args) {
LinkedList ll=new LinkedList();
Empp emp1=new Empp(“sa01”,“aa”,1.2f);
Empp emp2=new Empp(“sa02”,“bb”,1.2f);
Empp emp3=new Empp(“sa03”,“cc”,1.2f);
//addFirst表示把emp1加载(链表)队列的最前面
ll.addFirst(emp1);//addFirst方法是可以插入在数组之前
ll.addFirst(emp2);//也可以理解为addFirst方法是后进先出的方法
//addLast表示把emp3加载(链表)队列的后面
ll.addLast(emp3);
System.out.println(“测试LinkedList集合类中的addFist及addLast方法”);
for(int i=0;i<ll.size();i++){
System.out.println(((Empp)ll.get(i)).getName());
}
//remove表示将某一条数据进行删除
ll.remove(emp1);//将ll中的emp1数据删除
System.out.println(“测试LinkedList集合类中的remove方法”);
for(int i=0;i<ll.size();i++){
System.out.println(((Empp)ll.get(i)).getName());
}
ll.removeAll(ll);//清除整个链表
System.out.println(“测试LinkedList集合类中的remmoveall方法”);
for(int i=0;i<ll.size();i++){
System.out.println(((Empp)ll.get(i)).getName());
}
}
}
//创建员工类
class Empp{//在同一个包中的类,可以同包中的其它class文件直接访问或调用
//定义成员变量工号、姓名、薪水
private String empNo;
private String name;
private float sal;
//创建构造函数,初始化成员变量
public Empp(String empNo,String name,float sal){
this.empNo=empNo;
this.name=name;
this.sal=sal;
}
//使用set、get方法进行数据传递
public String getEmpNo() {
return empNo;
}
public void setEmpNo(String empNo) {
this.empNo = empNo;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public float getSal() {
return sal;
}
public void setSal(float sal) {
this.sal = sal;
}
}
1.3 Vector集合类
线程安全具有同步性
//Vector集合类(向量)的使用方法
import java.util.*;
public class Demo03 {
public static void main(String[] args) {
//Vector的用法
Vector vv=new Vector();
AEmp emp1=new AEmp(“1”,“aa”,1.2f);
AEmp emp2=new AEmp(“2”,“bb”,1.2f);
AEmp emp3=new AEmp(“3”,“cc”,1.2f);
vv.add(emp1);
vv.add(emp2);
vv.add(emp3);
//遍历
for(int i=0;i<vv.size();i++){
AEmp emp=(AEmp)vv.get(i);
System.out.println(emp.getName());
}
}
}
//创建员工类
class AEmp{
//定义成员变量工号、姓名、薪水
private String empNo;
private String name;
private float sal;
//创建构造函数,初始化成员变量
public AEmp(String empNo,String name,float sal){
this.empNo=empNo;
this.name=name;
this.sal=sal;
}
//使用set、get方法进行数据传递
public String getEmpNo() {
return empNo;
}
public void setEmpNo(String empNo) {
this.empNo = empNo;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public float getSal() {
return sal;
}
public void setSal(float sal) {
this.sal = sal;
}
}
1.4 Stack集合类(栈)
//Stack集合类(栈)的使用方法
package com.haiding.set;
import java.util.*;
public class Demo04 {
public static void main(String[] args) {
//Stack的用法
Stack stack=new Stack();
AEmp emp1=new AEmp(“s1”,“aa”,1.2f);
AEmp emp2=new AEmp(“s2”,“bb”,1.2f);
stack.add(emp1);
stack.add(emp2);
for(int i=0;i<stack.size();i++){
System.out.println(((AEmp)stack.get(i)).getName());
}
}
}
//创建员工类
class AEmp{
//定义成员变量工号、姓名、薪水
private String empNo;
private String name;
private float sal;
//创建构造函数,初始化成员变量
public AEmp(String empNo,String name,float sal){
this.empNo=empNo;
this.name=name;
this.sal=sal;
}
//使用set、get方法进行数据传递
public String getEmpNo() {
return empNo;
}
public void setEmpNo(String empNo) {
this.empNo = empNo;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public float getSal() {
return sal;
}
public void setSal(float sal) {
this.sal = sal;
}
}
总结
ArrayList和Vector的区别
ArrayList与Vector都是java的集合类,都可以用来存放java对象,
这是他们的相同点,但是他们也有区别:
1、同步性
Vector是线程同步的。这个类中的一些方法保证了Vector中的对象是线程安全的。
而ArrayList则是线程异步的,因此ArrayList中的对象并不是线程安全的。
因为同步的要求会影响执行的效率,
所以如果你不需要线程安全的集合那么使用ArrayList是一个很好的选择,
这样可以避免由于同步带来的不必要的性能开销。
2、数据增长
从内部实现机制来讲ArrayList和Vector都是使用数组(Array)来控制集合中的对象。
当你向这两种类型中增加元素的时候,
如果元素的数目超出了内部数组目前的长度它们都需要扩展内部数组的长度,
Vector缺省情况下自动增长原来一倍的数组长度,
ArrayList是原来的50%,所以最后你获得的这个集合所占的空间总是比你实际需要的要大。
所以如果你要在集合中保存大量的数据那么使用Vector有一些优势,
因为你可以通过设置集合的初始化大小来避免不必要的资源开销。
分为:HashMap类,Hashtable类
2.1 HashMap类
import java.util.*;
public class Demo05 {
public static void main(String[] args) {
//创建HashMap对象
HashMap hm=new HashMap();
Emp emp1=new Emp(“s001”,“aa”,3.4f);
Emp emp2=new Emp(“s002”,“bb”,5.6f);
Emp emp3=new Emp(“s003”,“cc”,1.2f);
//将emp放入到hm中
//hm.put(null,null);//可以放空值
hm.put(“s001”, emp1);
hm.put(“s002”, emp2);
hm.put(“s002”, emp3);//不允许key重复,所以emp3会覆盖emp2
//如果你要查找编号是s002
if(hm.containsKey(“s002”)){//取键值containsKey
System.out.println(“有该员工”);
//如何取出,键值
Emp emp=(Emp)hm.get(“s002”);
System.out.println(“名字”+emp.getName());
}else{
System.out.println(“没该员工”);
}
//遍历HashMap中所有的key和value值
//Iterator迭代
Iterator it=hm.keySet().iterator();
//hasNext返回一个boolean值
while(it.hasNext()){
//如果有下一个取出key值
String key=it.next().toString();
//通过key取出value
Emp emp=(Emp)hm.get(key);
System.out.println(“名字:”+emp.getName());
System.out.println(“工资:”+emp.getSal());
}
}
}
//创建员工类
class Emp{
//定义成员变量工号、姓名、薪水
private String empNo;
private String name;
private float sal;
//创建构造函数,初始化成员变量
public Emp(String empNo,String name,float sal){
this.empNo=empNo;
this.name=name;
this.sal=sal;
}
//使用set、get方法进行数据传递
public String getEmpNo() {
return empNo;
}
public void setEmpNo(String empNo) {
this.empNo = empNo;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public float getSal() {
return sal;
}
public void setSal(float sal) {
this.sal = sal;
}
}
2.2 Hashtable集合类
Hashtable具有同步性,线程安全
import java.util.*;
public class Demo06{
public static void main(String []args){
Hashtable ht=new Hashtable();//Hashtable与HsahMap在用法上一致
Emp emp4=new Emp(“s101”,“a1”,2.2f);
Emp emp5=new Emp(“s102”,“a2”,1.2f);
Emp emp6=new Emp(“s103”,“a3”,4.2f);
ht.put(“s101”, emp4);
ht.put(“s102”, emp5);
ht.put(“s103”, emp6);
//遍历
for(Iterator it=ht.keySet().iterator();it.hasNext()😉{
String key=it.next().toString();
Emp emp=(Emp)ht.get(key);
System.out.println(“名字:”+emp.getName()+“\t工资:”+emp.getSal());
}
}
}
//创建员工类
class Emp{
//定义成员变量工号、姓名、薪水
private String empNo;
private String name;
private float sal;
//创建构造函数,初始化成员变量
public Emp(String empNo,String name,float sal){
this.empNo=empNo;
this.name=name;
this.sal=sal;
}
//使用set、get方法进行数据传递
public String getEmpNo() {
return empNo;
}
public void setEmpNo(String empNo) {
this.empNo = empNo;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public float getSal() {
return sal;
}
public void setSal(float sal) {
this.sal = sal;
}
}
总结
HashMap和Hashtable集合类的区别
HashMap与Hashtable都是java的集合类,都可以用来存放java对象,这是他们的相同点,但是他们也有区别。
1、历史原因
Hashtable是基于陈旧的Dictionary类的,HashMap是java 1.2引进的Map接口的一个实现。
2、同步性
Hashtable是线程同步的。这个类中的一些方法保证了Hashtable中的对象是线程安全的。而HashMap则是线程异步的,因此HashMap中的对象并不是线程安全的。因为同步的要求会影响执行的效率,所以如果你不需要线程安全的集合那么使用HashMap是一个很好的选择,这样可以避免由于同步带来的不必要的性能开销,从而提高效率。
3、值
HashMap可以让你将空值作为一个表的条目的key或value但是Hashtable是不能放入空值的(null)
集合框架–深入讨论
进一步理解集合框架
java的设计者给我们提供了这些集合类,在后面编程中是相当有用的,具体什么时候用什么集合,要根据我们刚才分析的集合异同来选取。
如何选用集合类?
1、要求线程安全,使用Vector、Hashtable
2、不要求线程安全,使用ArrayList,LinkedList,HashMap
3、要求key和value键值,则使用HashMap,Hashtable
4、数据量很大,又要线程安全,则使用Vector
分为:HashSet类,TreeSet类
HashSet是基于HashMap实现的,HashSet底层采用HashMap来保存所有元素。
hashCode和equal()是HashMap用的,因为无需排序所以只需要关注定位和唯一性即可
hashCode是用来计算hash值的,hash值是用来确定hash表索引的
hash表中的一个索引存放的是一张链表,
所以还要通过equal方法循环比较链上的每一个对象才可以真正定位到键值对应的Entry
put时,如果hash表中没定定位到,就在链表前加一个Entry,
如果定位到了,则更换Entry中的value(值)并返回旧value(值)
覆写key的hashCode()和equal()时一定要注意,不要把它们和可变属性关联上,
否则属性变了之后hashCode会变,equal也会为false,
这样在Map中就找不到它了而且这样的对象因为找不到它所以得不到释放,这样就变成了一个无效引用(相当于内存泄漏)
3.1 HashSet集合
import java.util.*;
public class Demo07{
public static void main(String []args){
HashSet hs=new HashSet();
Emp emp1=new Emp(“s001”,“aa”,1.2f);
Emp emp2=new Emp(“s002”,“bb”,1.6f);
Emp emp3=new Emp(“s003”,“cc”,1.8f);
Emp emp4=new Emp(“s001”,“aa”,1.2f);
hs.add(emp1);
hs.add(emp2);
hs.add(emp3);
hs.add(emp4);
hs.add(emp1);//重复的emp1,HashSet会自动去除
System.out.println(“HashSet_size=”+hs.size());
System.out.println();
ArrayList al=new ArrayList();
Emp emp5=new Emp(“s004”,“dd”,1.0f);
Emp emp6=new Emp(“s005”,“ee”,2.5f);
al.add(emp5);
al.add(emp6);
//al.add(emp1);
hs.addAll(al);//将al中的值加到hs中,并去除重复的emp1
System.out.println(“HashSet_ArrayList_size=”+hs.size());
System.out.println();
//转换数组o[],遍历并输出HashSet中的无素
Object o[]=hs.toArray();
for(int i=0;i<o.length;i++){
System.out.println(“工号:”+((Emp)o[i]).getEmpNo()+“\t姓名:”+((Emp)o[i]).getName()+“\t工资:”+((Emp)o[i]).getSal());
}
}
}
class Emp{
private String empNo;
private String name;
private float sal;
public Emp(String empNo,String name,float sal){
this.empNo=empNo;
this.name=name;
this.sal=sal;
}
public String getEmpNo() {
return empNo;
}
public void setEmpNo(String empNo) {
this.empNo = empNo;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public float getSal() {
return sal;
}
public void setSal(float sal) {
this.sal = sal;
}
}
3.2 TreeSet集合
TreeSet集合类是一个有序集合,它的元素按照升序排序,默认是自然顺序排列,也就是说
TreeSet中的对象元素需要实现Comparable接口。
TreeSet与HashSet类一样没有get()方法来获取列表中的元素,所以也只能通过迭代器方法来获取。
由于TreeMap需要排序,所以需要一个Comparator为键值进行大小比较,
当然也是用Comparator定位的Comparator可以在创建TreeMap时指定,这时排序时使用Comparator.compare
如果创建时没有指定Comparator那么就会使用key.compareTo()方法,
这就要求key必须实现Comparable接口
TreeMap是使用Tree数据结构实现的,所以使用compare接口就可以完成定位了。
TreeSet是依靠TreeMap来实现的,TreeSet是一个有序集合,
它的元素按照升序排列,默认是按照自然顺序排列,也就是说TreeSet中的对象元素需要实现Comparable接口。
TreeSet类中跟HashSet类一要也没有get()方法来获取列表中的元素,所以也只能通过迭代器的方法来获取 。
import java.util.*;
public class Demo08{
public static void main(String[] args){
//传递一个比较器来实现你自己的排序方式
TreeSet tr =new TreeSet(new Student.StudentComparator());
tr.add(new Student(301,“张三”));//将学生数据写入TreeSet集合类的tr中
tr.add(new Student(201,“李二”));
tr.add(new Student(101,“王五”));
tr.add(new Student(101,“穷一”));
Iterator it=tr.iterator();//迭代器,遍历
while(it.hasNext()){//判断是否有下一个元素
System.out.println(it.next());
}
}
}
//创建Strudent学生类并实现Comparable与Comparator接口
class Student implements Comparable,Comparator{
private int num;//定义学号
private String name;//定义名字
public Student(int num,String name){
this.num=num;
this.name=name;
}
public int compareTo(Object o){
Student st=(Student)o;
int result;
result=num>st.num?1:(num==st.num?0:-1);//判断学号是否相同并返回result的值
//如果学号相等,就按姓名排列
/* if(result==0){
return name.compareTo(st.name);
}*/
return result;
}
//实现Comparator接口并实现它的抽象方法
public int compare(Object o1,Object o2){
Student st1 =(Student)o1;
Student st2 =(Student)o2;
return st1.name.compareTo(st2.name);//比较姓名是否相同
}
//重写toString()方法,因为如果不重写,打印出来的是16进制代码
public String toString(){
return “num=”+num+“; name=”+name;
}
public static class StudentComparator implements Comparator{//定义一个静态StudentComparator类并实现Comparator接口
public int compare(Object o1,Object o2){
Student st1 =(Student)o1;
Student st2 =(Student)o2;
int result;
result=st1.num>st2.num?1:(st1.num==st2.num?0:-1);//判断学号是否相同进行排序
if(result==0){//如果学号相等 就进行名字排序
result=st1.name.compareTo(st2.name);
}
return result;
}
}
}
总结
HashSet与TreeSet集合类的区别:
HashSet是基于hash算法实现的,性能优于TreeSet。
通常使用HashSet,在我们需要对其中元素排序的时候才使用TreeSet。
Queue接口与List、Set同一级别,都是继承了Collection接口。LinkedList实现了Queue接口。
Queue接口窄化了对LinkedList的方法的访问权限(即在方法中的参数类型如果是Queue时,就完全只能访问Queue接口所定义的方法了,而不能直接访问 LinkedList的非Queue的方法),
以使得只有恰当的方法才可以使用。BlockingQueue继承了Queue接口。
队列是一种数据结构。
它有两个基本操作:在队列尾部加人一个元素,和从队列头部移除一个元素。就是说,