51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

微信登录,快人一步

查看: 973|回复: 2

[原创文章] Java类库-Collection接口(重点)

[复制链接]

该用户从未签到

发表于 2019-9-26 15:14:40 | 显示全部楼层 |阅读模式
本帖最后由 璐璐 于 2019-9-26 15:22 编辑

测试做到一定程度,一定要懂得一些开发知识,这是一个不争的事实。从今天起,先给大家进行一系列开发知识的基础内容,都是原创,等到基础学完,会直接给大家开始更新自动化相关文章。先从JAVA的类库开始说起。
1】定义:Collection是整个类集中单值保存的最大父接口。即:每一次可以向集合里面保存一个对象。
2Collection接口里面定义有如下的几个常用操作方法。
   public boolean add(E e)--向集合里面保存数据
public boolean addAll(Collection<? extends E> c)--追加一个集合
public void clear()----清空集合,即根元素为null
public boolean contains(Object o)--判断是否包含指定的内容,需要equals()支持
public boolean isEmpty()-----------判断是否是空集合(不是null
public boolean remove(Object o)----删除对象,需要equals()支持
public int size()------------------取得集合中保存元素的个数
public Object[] toArray()-----将集合变为对象数组保存。
public Iterator<E> iterator()--Iterator接口实例化
注意:在所有的开发中add()iterator()方法的使用几率(99%)是最高的,其他方法几乎可以忽略。但是千万要记住contains()remove()两个方法一定要依靠equals()支持。
一般来说,我们掌握了一个接口的方法,然后就应该使用在子类为这个接口实例化并且使用,但是由于现在开发要去的严格性,所以不会在直接使用Collection接口,只会使用其子接口ListSet
下面我们就开始学习其两个子类接口:
一、List接口
目标:学习List子接口,我们做两件事情:
1、使用List子接口验证Colection接口中所提供的操作方法。
2、掌握List子接口的操作特点以及常用子类(ArraylistVector)。
请明确:List子接口是Collection中最为常用的子接口,使用率可达80%。同时这个接口对Collection接口进行了一些功能的扩充。在List子接口里重点掌握以下方法使用:
public E get(int index)--取得指定索引编号的内容,索引编号从0开始;
public E set(int index,E element)--修改指定索引编号的内容。
public ListIterator<E> listIterator(int index)--ListIterator接口进行实例化。
上述的三个方法中以get()方法最为重要。此时加上Collection本身的add()iterator()方法,这三个方法一定要掌握。
List本身是属于接口,所以如果要使用此接口进行操作,那么必须存在子类,可以使用Arraylist子类实现操作。(当然还有另外一个Vector子类,但是90%情况下采用ArrayList)。
3、新的子类:ArrayList
既然ArrayList类是List接口最为常用的一个子类,下面将利用此类来验证所学习到的操作。
【实例1List基本操作
  1. package com.list.demo;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. //实例1:List基本操作
  5. public class ListDemo01 {
  6.     public static void main(String[] args) {
  7.         List<String> all = new ArrayList<String>();//设置泛型,目的是:保证集合中所有元素类型的一致性
  8.         System.out.println("集合长度:"+all.size()+"集合是否为空:"+all.isEmpty());
  9.         all.add("hello");
  10.         all.add("hello");//重复元素
  11.         all.add("world");
  12.         System.out.println("集合长度:"+all.size()+"集合是否为空:"+all.isEmpty());
  13.         //Collection接口定义了size()方法可以取得集合长度。
  14.         //List子接口扩充了一个get()方法,可以根据索引得到数据。
  15.         for (int i = 0; i < all.size(); i++) {
  16.             String str = all.get(i);
  17.             System.out.println(str);
  18.         }
  19.     }
  20. }
复制代码

通过上述实例可以得出结论:List集合之中所保存的数据是按照保存的顺序进行存放的,而且允许存在有重复数据。但是一定要记住的是,List子接口扩充有get()方法。
【示例2】为Collection接口实例化
因为ArrayListList接口的子类,而List又是Collection子接口,自然可以通过ArrayListCollection进行实例化。
  1. package com.list.demo;

  2. import java.util.ArrayList;
  3. import java.util.Collection;

  4. //通过Collection接口进行实例化
  5. public class CollectionDemo01 {
  6. public static void main(String[] args) {
  7.     Collection<String> co = new ArrayList<String>();
  8.     System.out.println("集合长度:"+co.size()+"集合是否为空:"+co.isEmpty());
  9.     co.add("hello");
  10.     co.add("hello");//重复插入元素
  11.     co.add("world");
  12.     //由于Collection接口是没有get方法的,所以我们此时想要输出集合中的元素,只能借用对象数组。
  13.     Object obj[] = co.toArray();
  14.     for (int i = 0; i < obj.length; i++) {
  15.         System.out.println(obj[i]);
  16.     }
  17. }
  18. }
复制代码

-----上述代码爱会不会没啥用
但是请记住:上面这种实现集合输出的方式永远都不会用到,没必要纠结。我们可以看出Collection接口与List接口相比,功能会显得有所不足。而且以上所使用的输出方式并不是集合所会使用到的标准输出结构,只是做一个基础的展示。

回复

使用道具 举报

该用户从未签到

 楼主| 发表于 2019-9-26 15:15:08 | 显示全部楼层
本帖最后由 璐璐 于 2019-9-26 16:50 编辑

【范例3】在集合里面保存对象
  1. package com.list.demo;

  2. import java.util.ArrayList;
  3. import java.util.List;

  4. class Book{
  5.     private String title;
  6.     private float price;
  7.     public Book(String title,float price){
  8.         this.title = title;
  9.         this.price = price;
  10.     }
  11.    
  12.     @Override
  13.     public String toString() {
  14.         return "书名:"+this.title+"价格:"+this.price+"\n";
  15.     }
  16.     @Override
  17.     public boolean equals(Object obj) {
  18.     if(this==obj){
  19.         return true;
  20.     }if(obj==null){
  21.         return false;
  22.     }if(!(obj instanceof Book)){
  23.         return false;
  24.     }
  25.     Book book =(Book) obj;
  26.     if(this.title.equals(book.title)&&this.price==book.price){
  27.         return true;
  28.     }
  29.     return false;
  30.     }
  31. }
  32. public class ListDemo02 {

  33.     public static void main(String[] args) {
  34.         List<Book> all = new ArrayList<Book>();
  35.         all.add(new Book("JAVA开发", 79.80f));
  36.         all.add(new Book("JSP开发", 69.80f));
  37.         //任何情况下集合的数据删除与内容的查询都必须提供由equals()方法,默认的操作是按照地址进行比较的。
  38.         all.add(new Book("Oracle开发", 89.80f));
  39.         all.remove(new Book("Oracle开发", 89.80f));
  40.         System.out.println(all);
  41.         
  42.     }

  43. }
复制代码


与之前的链表相比,几乎是横向替代就是替换了一个类名称,因为给出的链表就是按照Collection与List接口的方法标准定义的。

总结下Object中的方法都可以做什么用???
二、旧的子类Vector

【范例1】使用Vector
  1. package com.list.demo;

  2. import java.util.ArrayList;
  3. import java.util.List;
  4. import java.util.Vector;

  5. //实例1:List基本操作
  6. public class ListDemo01 {

  7. public static void main(String[] args) {
  8. List<String> all = new Vector<String>();//设置泛型,目的是:保证集合中所有元素类型的一致性
  9. System.out.println("集合长度:"+all.size()+"集合是否为空:"+all.isEmpty());
  10. all.add("hello");
  11. all.add("hello");//重复元素
  12. all.add("world");
  13. System.out.println("集合长度:"+all.size()+"集合是否为空:"+all.isEmpty());
  14. //Collection接口定义了size()方法可以取得集合长度。
  15. //List子接口扩充了一个get()方法,可以根据索引得到数据。
  16. for (int i = 0; i < all.size(); i++) {
  17. String str = all.get(i);
  18. System.out.println(str);
  19. }
  20. }

  21. }
复制代码



补充:请解析ArrayList与Vector的区别。

NO 区别点 ArrayList(90%使用) Vector
1 推出时间 JDK1.2推出,属于新的类 JDK1.0,属于旧的类
2 性能 异步处理 同步处理
3 数据安全 非线程安全 线程安全
4 输出 支持Iterator、list
Iterator、foreach
支持Iterator、list
Iterator、foreach、Enumeration
请记住:在以后开发中,如果采用List子接口就使用ArrayList子类。

结论:

(1)List中的数据保存顺序就是数据的添加顺序。

(2)List集合中可以保存重复的元素。

(3)List子接口比Collection接口扩充了一个get()方法。

(4)List选择子类就使用Arraylist。

二、Set子接口

[一]学习目标

1、Set子接口的操作特点以及常用子类。

2、深入分析两个常用子类的操作特征。


回复 支持 反对

使用道具 举报

该用户从未签到

 楼主| 发表于 2019-9-26 15:15:20 | 显示全部楼层
本帖最后由 璐璐 于 2019-9-26 16:49 编辑

【二】具体内容

        在Collection接口下又有另外一个比较常用的子接口Set接口(一般使用率也就是20%),Set接口并不像List接口那样对于Collection接口进行大量扩充,而是简单继承了Collection接口,也就没有List集合所提供的get()方法。Set接口下有两个常用的子类:HashSet与TreeSet

【实例1】观察HashSet子类的特点
  1. package com.set.demo;

  2. import java.util.HashSet;
  3. import java.util.Set;

  4. public class SetD {

  5. public static void main(String[] args) {
  6. Set<String> all = new HashSet<String>();
  7. all.add("nihao");
  8. all.add("hello");
  9. all.add("hello");//重复数据
  10. all.add("world");
  11. System.out.println(all);
  12. }

  13. }
复制代码



程序运行的结果为:
  1. [world, nihao, hello]
复制代码



  通过实例1我们不难发现:Set集合下没有重复元素(这一点也是Set接口的重要特征),同时发现在里面所保存的数据是没有任何顺序的,即:HashSet的子类特征属于无序排列。

【实例2】使用TreeSet子类
  1. package com.set.demo;
  2. import java.util.Set;
  3. import java.util.TreeSet;
  4. public class TreeSetDemo {
  5. public static void main(String[] args) {
  6. Set<String> all = new TreeSet<String>();
  7. all.add("X");
  8. all.add("B");
  9. all.add("A");
  10. all.add("B");//重复数据
  11. System.out.println(all);
  12. }
  13. }
复制代码



文章来源:海哥说测试   
作者:博为峰网校金牌讲师        haibao1371

运行结果为:[A, B, X]


此时的程序使用TreeSet子类,发现没有重复数据,以及所保存的内容自动排序。

【三】数据排序的说明(重点):

既然TreeSet子类保存的内容可以进行排序,那么下面不如就编写一个自定义的类来完成数据的保存。

首先我们看如下代码:

package com.set.demo;

import java.util.Set;
import java.util.TreeSet;

//自定义存储对象
class Book{
private String title;
private float price;
public Book(String title,float price){
this.title = title;
this.price = price;
}
@Override
public String toString() {
return "书名:"+this.title+"价格:"+this.price+"\n";
}
}
public class TreeSetDemo02 {

public static void main(String[] args) {
Set<Book> all = new TreeSet<Book>();
all.add(new Book("java开发", 79.8f));
all.add(new Book("java开发", 79.8f));//全部信息重复
all.add(new Book("jsp开发", 79.8f));//价格信息重复
all.add(new Book("android开发", 89.8f));//都不重复
System.out.println(all);
}

}

其运行结果为:
Exception in thread "main" java.lang.ClassCastException: com.set.demo.Book cannot be cast to java.lang.Comparable
at java.util.TreeMap.compare(Unknown Source)
at java.util.TreeMap.put(Unknown Source)
at java.util.TreeSet.add(Unknown Source)
at com.set.demo.TreeSetDemo02.main(TreeSetDemo02.java:23)

上述代码的报错原因是:集合就是一个动态的对象数组,那么如果要想为一组对象进行排序,在JAVA里面必选要使用比较器,应该使用Comparable完成比较。在比较方法里面需要将这个类的所有属性都一起参与到比较之中。

那么此时我们将上述报错代码进行改造:改造结果如下所示:
package com.set.demo;
import java.util.Set;
import java.util.TreeSet;
//自定义存储对象
class Book implements Comparable<Book>{
private String title;
private float price;
public Book(String title,float price){
this.title = title;
this.price = price;
}
@Override
public String toString() {
return "书名:"+this.title+"价格:"+this.price+"\n";
}
public int compareTo(Book book) {
if(this.price>book.price){
return -1;
}else if(this.price<book.price){
return 1;
}else{
return 0;
}
}
}
public class TreeSetDemo02 {

public static void main(String[] args) {
Set<Book> all = new TreeSet<Book>();
all.add(new Book("java开发", 79.8f));
all.add(new Book("java开发", 79.8f));//全部信息重复
all.add(new Book("jsp开发", 79.8f));//价格信息重复
all.add(new Book("android开发", 89.8f));//都不重复
System.out.println(all);
}
}

此时执行结果为:
【书名:android开发价格:89.8
, 书名:java开发价格:79.8
]
我们不难看出,TreeSet类主要是依靠Comparable接口中的compareTo()方法判断是否是重复数据,如果返回的是0,那么他就认为是重复数据,不会被保存。



所以要想实现真正的比较,必须在比较方法里面将这个类的所有属性都一起参与到比较之中。我们上述代码已经实现比较price,现在把String类型的title也加入到比较之中,由于String类也可以实现Comparable接口。所以也存在compareTo()方法,此时代码改造如下:
package com.set.demo;

import java.util.Set;
import java.util.TreeSet;

//自定义存储对象
class Book implements Comparable<Book>{
private String title;
private float price;
public Book(String title,float price){
this.title = title;
this.price = price;
}
@Override
public String toString() {
return "书名:"+this.title+"价格:"+this.price+"\n";
}
public int compareTo(Book book) {
if(this.price>book.price){
return -1;
}else if(this.price<book.price){
return 1;
}else{
return this.title.compareTo(book.title);//调用了String类的比较大小。
}
}
}
public class TreeSetDemo02 {

public static void main(String[] args) {
Set<Book> all = new TreeSet<Book>();
all.add(new Book("java开发", 79.8f));
all.add(new Book("java开发", 79.8f));//全部信息重复
all.add(new Book("jsp开发", 79.8f));//价格信息重复
all.add(new Book("android开发", 89.8f));//都不重复
System.out.println(all);
}
}

此时运行结果为:
[书名:android开发价格:89.8
, 书名:java开发价格:79.8
, 书名:jsp开发价格:79.8
]




我们可以得出结论:CompareTo()方法只对TreeSet有效,对于HashSet是无效的,不会消除其重复数据。
【四】关于重复元素的说明(重点):

重申下:Comparable接口只能负责TreeSet子类进行重复元素的判断,它并不是真正的用于能够进行重复元素验证的操作。如果要想判断重复元素那么只能依靠Object类中所提供的方法。

【1】取得哈希码:public int hashCode():

——先判断对象的哈希码是否相同,依靠哈希码取得一个对象的内容。

【2】对象比较:public boolean equals(Object obj):

——再将对象的属性进行依次的比较。

那么问题来了,上面提到的两个方法怎么书写,非常复杂,没人会。打开开发工具Eclipse——Source——选择Generate hashCode()andequals,选择属性后会自动生成。改造后的代码如下:
package com.set.demo;
import java.util.HashSet;
import java.util.Set;
import java.util.TreeSet;
//自定义存储对象
class Book01{
private String title;
private float price;
public Book01(String title,float price){
this.title = title;
this.price = price;
}
@Override
public String toString() {
return "书名:"+this.title+"价格:"+this.price+"\n";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + Float.floatToIntBits(price);
result = prime * result + ((title == null) ? 0 : title.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Book01 other = (Book01) obj;
if (Float.floatToIntBits(price) != Float.floatToIntBits(other.price))
return false;
if (title == null) {
if (other.title != null)
return false;
} else if (!title.equals(other.title))
return false;
return true;
}
}
public class HashSetDemo02 {

public static void main(String[] args) {
Set<Book01> all = new HashSet<Book01>();
all.add(new Book01("java开发", 79.8f));
all.add(new Book01("java开发", 79.8f));//全部信息重复
all.add(new Book01("jsp开发", 79.8f));//价格信息重复
all.add(new Book01("android开发", 89.8f));//都不重复
System.out.println(all);
}
}

运行结果为:
[书名:jsp开发价格:79.8
, 书名:java开发价格:79.8
, 书名:android开发价格:89.8
]
不难看出:已经消除了重复数据。

可以得出结论:以后在非排序的情况下,只要是判断重复元素依靠的永远都是hashCode()与equals()。

下面对Set接口进行总结:

【1】在开发之中,Set接口绝对不是首选,如果真要使用也建议使用HashSet子类。

【2】Comparable这种比较器大部分情况下只会存在于JAVA的理论范畴内。例如:要进行TreeSet排序,大部分的企业平台开发,都不会使用TreeSet。

【3】Set不管如何操作,必须始终保持一个前提:数据不能够重复。

回复 支持 反对

使用道具 举报

本版积分规则

关闭

站长推荐上一条 /1 下一条

小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

GMT+8, 2024-3-29 10:03 , Processed in 0.070995 second(s), 23 queries .

Powered by Discuz! X3.2

© 2001-2024 Comsenz Inc.

快速回复 返回顶部 返回列表