List接口
Collection接口下有两个子接口
一个是List,一个是Set
List可以储存重复的对象
列表List有一个特有的迭代器->ListIterator ListIterator() 接口,这个接口可以把集合List的元素在迭代过程中进行增删改查的行为
如:在迭代列表集合时,添加,覆盖…集合元素
List list=new ArrarList();
list.add("itcast1");
list.add("itcast2");
list.add("itcast3");
在迭代的过程中!想判断是否含有对象 itcast2 如果有那么,将其覆盖,或者在它后面加新对象
ListIterator it=list.ListIterator();
while(it.hasNext())
{
Object obj=it.next();
if("itcast2".equals(obj)
{
it.add("java");//如果元素中有itcast2,那么在它后面的位置添加java
it.set("java");//如果集合中有itcast2,那么用java将其覆盖掉
//这里调用的都输列表迭代器的方法
}
}
List本身也具有方法,比如add,add(int index,Object obj),remove,get(int index)
由于List允许重复对象的存在,但是去重复对象,只保留净对象也是常用操作
去list的重复
1.创建一个新的容器,通过迭代遍历来储存筛选出来的元素
2.将原容器清空
3.将新容器的内容全部复制到原容器中
public static void getSingleElement(List list)
{
List temp=new ArrayList();
for(Iterator it=list.itrator();it.hasNext();)
{
Objcet obj=it.next();//不用使用集合中对象的特有方法,所以不需要向下转型
if(!temp.contains(obj)// 集合contains方法的本质是Object的equals方法,也就是比较地址值,所以如果想要比较自己设定的对象,那么就需要重写equals方法
{
temp.add(obj);
}
list.clear;
list.addAll(temp);
}
)
上面提到要重写equals方法
就拿学生为例,姓名和年龄相同即为重复
class Student
{
private String name;
private int age;
public boolean equals(Object obj)
{
if(this==obj)
return ture;
if(!(obj instanceof Student))//尽管向上转型,但是obj对象,还是属于Student的实例
{
throw new ClassCastException();
}
Student stu=(Student) obj;
return this.name.equals(stu.name)&&this.age==stu.age;
}
}
set接口
不允许重复元素出现的集合
如果是字符串类型作为元素添加在set集合中,那么会自动去重复,如果是自己定义的对象的话呢?
Set set=new HashSet();
set.add("abc");
set.add("abc");
set.add("abcd");
set.add("abcd");
for(Iterator it=set.itretor();it.hasNext();)
{
Object obj=it.next();
System.out.println(obj);
}//abc,abcd
自动去重复
原理是什么呢? 是因为Set的数据结构是哈希表,也就是说,在set.add()方法调用的时候,先调用了元素对象的hashcode()方法,然后根据返回结果存入数组里,然后再equals方法来比较地址 (字符串就是比较自身内容)
就拿字符串为例,第一个abc和第二个bac的哈希值是相同的,然后比较内容,内容相同即为重复,所以数组只添加一次abc
如果是自己定义的对象呢?
同理,也是先调用对象的hashcode方法,找位置,然后再调用equals来比较,equals返回值为false,不重复,那么连在后面(链表)
所以,如果是自己定义的对象存在set里,要想去重复
要重写添加元素对象hashcode和equals方法
@override
public int hashcode()
{
return 1;
}
public boolean equals(Object obj)
{
if(this==obj)
return ture;
if(!(obj instanceof Student))//尽管向上转型,但是obj对象,还是属于Student的实例
{
throw new ClassCastException();
}
Student stu=(Student) obj;
return this.name.equals(stu.name)&&this.age==stu.age;
}
所以你定义的对象哈希值都为1,然后就比较你定义的重复->学生的姓名与年龄,如果重复那么去掉。
但是如果重写的hashcode()返回值一直是1,
那么,先比哈希值就没有意义,因为只会在数组的某个位置,创建链表,然后根据equals()来决定是否添加。
所以,为了提高效率,应该返回特有的哈希值:
public int hashcode()
{
return name.hashcode()+this.age;
}
Set的另一个子接口:TreeSet接口–不仅去重复,并且会自动将添加进来的元素进行排序!
TreeSet集合也会保证元素的唯一性 ,那它是怎么保证的呢???和HashSet一样吗??
不一样!!!因为数据结构不同!!
TreeSet set=new TreeSet();
set.add(new Student("zhangshan",21));// TreeSet的add方法,是将元素对象转成Comparable类型,就是实现接口的意思:calss Student implments Comparable
//然后调用Comparable的compareTo()方法
//所以就是要重写这个方法
public int compareTo(Object obj)
{
if(!(obj instanceof Student))
{
throw new ClassCastException();
}
Student stu=(Student)obj;
int temp=this.age-stu.age;
return temp==0? this.name.compareTo(stu.name):0;
}
compareTo()如果返回值是0的话,就判定obj和this相同,然后就不会储存!!!如果结果小于0,将小的对象放在二叉树的左孩子树,将大的对象放二叉树的右孩子树,后面添加的对象,采用折中比较的方式,
来提高比较效率。(左小右大)
比较除了上面那种形式,还可以采取Comparator(比较器)的方式,在TreeSet创建对象的时候使用,而不需要在元素对象里面重写compareTo()方法:
calss CompareByName implements Comparator
{
public int compare(Object obj1,Object obj2)//重写Comparetor的compare()方法
{
Student s1=(Student)obj1;
Student s2=(Student)obj2;
int temp=s1.getName().compareTo(s2.getName());//字符串默认的compareTo方法,采取相减的方式进行比较//比较姓名是第一比较因素
return temp==0?s1.getAge()-s2.getAge():0;
}
}
TreeSet set=new TreeSet(new CompareByName());
set.add(new Student("woirniam",21));
set.add(new Student("wocainimo",23));
以上就是TreeSet去重复而且排序的方法!Comparetor,Comparable接口,可以用在任何地方,不仅仅是这里。
小点:Comparetor接口还有一个方法 equals () 这个只是用来判断你创建的得比较器对象是否相同,这个是Object的实例方法(抽象类可以含有实例方法但是接口只能有抽象方法),没有重写。