关于JDK中的集合总结(二)
1.2版本的JDK才出现的java集合框架。
下面介绍说一下Vector的一些特点。
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Vector;
public class VectorDemo {
public static void main(String[] args) { Vector v = new Vector();
v.addElement("abc1");
v.addElement("abc2");
v.addElement("abc3");
v.addElement("abc4"); Enumeration en = v.elements();
while(en.hasMoreElements()){
System.out.println("nextelment:"+en.nextElement());
}
Iterator it = v.iterator();
while(it.hasNext()){
System.out.println("next:"+it.next());
}
}
}
方法名上只要有Elements的都是Vector特有 的方法。
Vector中有一个elements()方法。
elements() |
接口 Enumeration<E>
注:此接口的功能与 Iterator 接口的功能是重复的。此外,Iterator 接口添加了一个可选的移除操作,并使用较短的方法名。新的实现应该优先考虑使用 Iterator 接口而不是 Enumeration 接口。
从以下版本开始:
JDK1.0
Enumeration接口也是很早就出现的,但是现在基本上不用了,在jdk2.0之前都是使用该方法进行遍历的,那时候还没有Iterator接口。但是由于其名字比较长,而郁郁而终。
例如,要输出 Vector<E> v 的所有元素,可使用以下方法:
for (Enumeration<E> e = v.elements(); e.hasMoreElements();)
System.out.println(e.nextElement());
上面是java API中的描述,重点是使用了for循环。
LinkedList
void |
|
void |
|
getFirst() |
|
getLast() |
remove() |
|
remove(int index) |
LinkedList:
addFirst();
addLast():
jdk1.6
offerFirst();在此列表的开头插入指定的元素
offerLast();在此列表末尾插入指定的元素。
getFirst();.//获取但不移除,如果链表为空,抛出NoSuchElementException.
getLast();
jdk1.6
peekFirst();//获取但不移除,如果链表为空,返回null.
peekLast():
removeFirst();//获取并移除,如果链表为空,抛出NoSuchElementException.
removeLast();
jdk1.6
pollFirst();//获取并移除,如果链表为空,返回null.
pollLast();
自动装箱:基本数据类型转换成引用数据类型。
自动拆箱:引用数据类型和基本数据类型做运算的时候。
ArrayList集合存储自定对象:
Person.java
public class Person {
private String name;
private int age;
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 Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
}
ArrayListTest.java
import java.util.ArrayList;
import java.util.Iterator;
public class ArrayListTest {
public static void main(String[] args) {
ArrayList list = new ArrayList(); list.add(new Person("lisi1",11));
list.add(new Person("lisi2",12));
list.add(new Person("lisi3",13));
list.add(new Person("lisi4",14)); Iterator it =list.iterator();
while(it.hasNext()){
//System.out.println(((Person) it.next()).getName()+"--"+((Person) it.next()).getAge());
//输出:
//lisi1--12
//lisi3—-14 出现名字和姓名交错的现象原因就是next()访问完一个对象之后接着去访问下一个对象。
Person p = (Person) it.next();
System.out.println(p.getName()+"----"+p.getAge());
}
}
}
输出结果:
lisi1----11
lisi2----12
lisi3----13
lisi4----14
Set:元素不可以重复,是无序的。
Set接口中的方法和Collection一致。
|--HashSet: 内部数据结构是哈希表 ,是不同步的。
如何保证该集合的元素唯一性呢?
是通过对象的hashCode和equals方法来完成对象唯一性的。
如果对象的hashCode值不同,那么不用判断equals方法,就直接存储到哈希表中。
如果对象的hashCode值相同,那么要再次判断对象的equals方法是否为true。
如果为true,视为相同元素,不存储。如果为false,那么视为不同元素,就进行存储。
记住:如果元素要存储到HashSet集合中,必须覆盖hashCode方法和equals方法。
一般情况下,如果定义的类会产生很多对象,比如人,学生,书,通常都需要覆盖equals,hashCode方法。
建立对象判断是否相同的依据。
哈希算法是底层windows做的,而且针对不同的对象有不同的哈希算法运算。
java类中有的哈希算法是native用的windows底层 的,有的根据对象的不同进行了重写。
哈希表:哈希这种算法会算出很多的值,把这些值存储起来形成一个表。表中有对应关系。
哈希表中还是数组。只是哈希这种算法对数组进行了优化。
哈希算法有一种最常见的算法就是取余。
哈希表中不能有重复的元素。
哈希表是如何判断元素是否是重复的?
“ab”和”ba”产生的哈希值是一样的,取余之后都是5,但是内容不一样,哈希值对这样的情况也有对应的方法,在5角标出“挂”一个”ba”。
在list集合remove和contains都要判断相不相同,都是用的equals、
如果到了set集合,要删除一个元素,要依据该元素是否和该容器中的元素是否相同。
hashset依据hashcode和equals。
用HashSet存储自定义对象
Person.java
public class Person {
private String name;
private int age;
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 Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
}
HashSetTest.java
import java.util.HashSet;
import java.util.Iterator;
public class HashSetTest {
public static void main(String[] args) {
HashSet set = new HashSet();
set.add(new Person("lisi1",11));
set.add(new Person("lisi2",12));
set.add(new Person("lisi3",13));
set.add(new Person("lisi4",14));
set.add(new Person("lisi4",14));
Iterator it = set.iterator();
while(it.hasNext()){
Person p = (Person) it.next();
System.out.println(p.getName()+"---"+p.getAge());
}
}
}
打印的结果是:
lisi3---13
lisi4---14
lisi1---11
lisi2---12
lisi4---14
集合中存储进去了两个“lisi4 14”又是集合Set ,Set集合中不会再存储相同的元素。为什么出现这种情况。
首先这是Set存储用户自定义对象。
其次Person类继承的是Object,每new一个Person都有不同的地址值,hashcode不同,对于Set集合来说是不同的元素。
第三你自己定义的只要名字和年龄一样就是不同的对象这个规则程序现在是不知道的。需要你自己去定义,完善。
修改之后的代码:
Person.java
public class Person extends Object {
private String name;
private int age;
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 Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
//hashCode()方法返回的是一个int类型的值,这里根据Person类对象的特点,返回一个由name和age属性决定的值最合适。age之后乘以的数字只要不是1,都可以。
@Override
public int hashCode() {
System.out.println(this+".......hashCode");
return name.hashCode()+age*27;
}
@Override
public boolean equals(Object obj) {
if(this == obj)
return true;
if(!(obj instanceof Person))
throw new ClassCastException("类型错误");
System.out.println(this+"....equals....."+obj);
Person p = (Person)obj;
return this.name.equals(p.name) && this.age == p.age;
}
public String toString(){
return name +":"+ age;
}
}
从输出的结果可以看出来,这两句if语句并没有执行,因为如果执行了就不会再执行下面的语句了,if中的语句是return结束语句。我在debug模式下inspect监察if中的语句也都是false。
第二if语句感觉到确实是有用,第一句有什么用处呢?
第一if语句的用处就在于,当判断完hashCode()方法之后hash值相同,如果内容也相同,就用if(this ==obj),这样结束equals语句中的判断。
在写上面这段代码时候,我没有重写toString方法,程序就会报错。
Exception in thread "main" java.lang.StackOverflowError
at java.lang.Object.toString(Unknown Source)
at java.lang.String.valueOf(Unknown Source)
at java.lang.StringBuilder.append(Unknown Source)
at Mypack.Person.hashCode(Person.java:26)
如果不重写此方法打印的就是对象,如果不重写toString就是打印的hashcode值,但是这里重写了hashCode方法。
HashSetTest.java
import java.util.HashSet;
import java.util.Iterator;
public class HashSetTest {
public static void main(String[] args) {
HashSet set = new HashSet();
set.add(new Person("lisi1",11));
set.add(new Person("lisi2",12));
set.add(new Person("lisi3",13));
set.add(new Person("lisi4",14));
set.add(new Person("lisi4",14));
Iterator it = set.iterator();
while(it.hasNext()){
Person p = (Person) it.next();
//System.out.println(p);
System.out.println(p.getName()+"---"+p.getAge());
}
}
}
输出:
lisi1:11.......hashCode
lisi2:12.......hashCode
lisi3:13.......hashCode
lisi4:14.......hashCode
lisi4:14.......hashCode
lisi4:14....equals.....lisi4:14
lisi2---12
lisi1---11
lisi4---14
lisi3---13
从上面的输出可以看出在初始化Set集合的时候调用了hashCode()方法,在初始化第二个lishi4的时候set就对其中的元素进行了check,用到了equals方法。
System.out.println(age.hashCode());
System.out.println(name.hashCode());
当时很纳闷name作为一个类中的属性,怎么能有hashCode()方法呢?hashCode()方法不是对象才所具有的吗?于是我就尝试打印age的哈希值,报这个错误:Cannot invoke hashCode() on the primitive type int。
hashCode()确实只有对象才有,但是age是个int类型的,name是String类型的,String类型是对象类型。所以name属性有hashCode()方法。
/*
* 定义功能去除ArrayList中的重复元素。
*/
Person.java
public class Person extends Object {
private String name;
private int age;
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 Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String toString(){
return name +":"+ age;
} @Override
public boolean equals(Object obj) { if(this == obj)
return true;
if(!(obj instanceof Person))
throw new ClassCastException("类型错误");
Person p = (Person)obj;
return this.name.equals(p.name) && this.age == p.age;
}
}
ArrayList中判断元素是否存在就只重写了一个equals()方法。
用equals()方法来判断对象的属性值是否都相同。
ArrayListTest2 .java
public class ArrayListTest2 {
public static void main(String[] args) {
ArrayList al = new ArrayList();
al.add(new Person("lisi1",21));
al.add(new Person("lisi2",22));
al.add(new Person("lisi3",23));
al.add(new Person("lisi4",24));
al.add(new Person("lisi2",22));
al.add(new Person("lisi3",23)); System.out.println(al);
al = getSingleElement(al); System.out.println(al.remove(new Person("lisi2",22))); //返回值是true
//虽然这个地方new的是一个新对象,但是remove还是把arraylist中的以有该数据删除,因为关键的地方是contains中判断的就是equals,
//equals两个数据内容相同则视为同一个元素,remove返回的是boolean。
System.out.println(al);
}
public static ArrayList getSingleElement(ArrayList list) {
ArrayList temp = new ArrayList();
Iterator it = list.iterator();
while(it.hasNext()){
Object obj = it.next();
//判断被迭代到的元素是否在临时容器中存在
if(!temp.contains(obj)){
temp.add(obj);
}
}
return temp;
}
}
输出:
[lisi1:21, lisi2:22, lisi3:23, lisi4:24, lisi2:22, lisi3:23]
true
[lisi1:21, lisi3:23, lisi4:24]
LinkedHashSet
HashSet是无序的,但是其下的小弟是有有序功能的,就是LinkedHashSet。
具有可预知迭代顺序的 Set 接口的哈希表和链接列表实现。
保证唯一还要有序就直接用LinkedHashSet.就可以实现。
HashSet hs = new LinkedHashSet();
|--TreeSet:可以对Set集合中的元素进行排序。是不同步的,即是线程不安全的。
判断元素唯一性的方式:就是根据比较方法compareTo()的返回结果是否是0,是0,就是相同元素,不存。
集合中判断元素不同的方式???
Set中其他的都根据hashcode和equals方法。
TreeSet对元素进行排序的方式一:
让元素自身具备比较功能,就需要实现Comparable接口。覆盖compareTo方法。
如果不要按照对象中具备的自然顺序进行排序。如果对象中不具备自然顺序。怎么办?
可以使用TreeSet集合第二种排序方式二:
让集合自身具备比较功能,定义一个类实现Comparator接口,覆盖compare方法。
将该类对象作为参数传递给TreeSet集合的构造函数。
TreeSet是排序用的,有排序就需要比较。
public interface Comparable<T>
此接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的 compareTo 方法被称为它的自然比较方法。
compareTo
int compareTo(T o)
比较此对象与指定对象的顺序。如果该对象小于、等于或大于指定对象,则分别返回负整数、零或正整数。
只要对象需要比较就要实现这个接口。
字符串String 本身就实现了Comparable接口,可以直接进行排序。
public int compareTo(Object o) { Person p = (Person)o; int temp = this.age-p.age;
return temp==0?this.name.compareTo(p.name):temp; int temp = this.name.compareTo(p.name);
return temp==0?this.age-p.age:temp;
}
集合自身具有比较性,具有两个才能比。而元素自身具有比较性传一个就能比,元素自身是一个对象。
TreeSet(
Comparator<? super
E> comparator)
构造一个新的空 TreeSet,它根据指定比较器进行排序。
接口 Comparator<T>
|
compare
int compare(T o1,T o2)
比较用来排序的两个参数。根据第一个参数小于、等于或大于第二个参数分别返回负整数、零或正整数。
TreeSet具备比较器,Person具备自然排序,进行元素比较时以TreeSet为主。开发中也是。
java中的很多类都实现了Comparable接口。String,Integer。
凡是一个类具备n多对象的,基本上都实现了这个接口,让其具备比较性。
这个是类的默认比较方式。如果想指定的话最好使用比较器进行。
TreeSetDemo.java
TreeSet ts = new TreeSet(new ComparatorByName());
让TreeSet集合对象在一开始初始化的时候就具备一个比较器。
ComparatorByName.java
姓名比较器的具体实现:
import java.util.Comparator;
/**
* 创建了一个根据Person类的name进行排序的比较器。
*/
public class ComparatorByName implements Comparator { @Override
public int compare(Object o1, Object o2) {
Person p1 = (Person)o1;
Person p2 = (Person)o2; int temp = p1.getName().compareTo(p2.getName()); return temp==0?p1.getAge()-p2.getAge(): temp;
}
}
根据字符串的长度设置比较器。
ComparatorByLength.java
public class ComparatorByLength implements Comparator {
@Override
public int compare(Object o1, Object o2) {
String s1 = (String)o1;
String s2 = (String)o2; int temp = s1.length()-s2.length(); return temp==0? s1.compareTo(s2): temp;
}
}
if(this.hashCode()== obj.hashCode() && this.equals(obj))
哈希表确定元素是否相同
1,判断的是两个元素的哈希值是否相同。
如果相同,在判断两个对象的内容是否相同。
2,判断哈希值相同,其实判断的是对象的hashCode的方法。判断内容相同,用的是equals方法。
注意:如果哈希值不同,是不需要判断equals。
关于JDK中的集合总结(二)的更多相关文章
- Java中的集合(十二) 实现Map接口的WeakHashMap
Java中的集合(十二) 实现Map接口的WeakHashMap 一.WeakHashMap简介 WeakHashMap和HashMap一样,WeakHashMap也是一个哈希表,存储的也是键值对(k ...
- Java中的集合(二)单列集合顶层接口------Collection接口
Java中的集合(二)单列集合顶层接口------Collection接口 Collection是一个高度封装的集合接口,继承自Iterable接口,它提供了所有集合要实现的默认方法.由于Iterab ...
- 关于JDK中的集合总结(一)
静态方法只能继承,不能重写(Override). StringBufffer,数组,对象 都是容器. 加入数据,“zhangsan” true ,67, 三个数据数据类型不同,不能用数组作为集合,只能 ...
- 关于JDK中的集合总结(三)
泛型: jdk1.5出现的安全机制. 好处: 1,将运行时期的问题ClassCastException转到了编译时期. 2,避免了强制转换的麻烦. <>:什么时候用?当操作的引用数据类型不 ...
- 集合篇 —— Collection(1):JDK 中的重复实现问题
1. 问题的提出 在 Java 的集合体系当中,无论是 List(列表)还是 Set(集),在设计的时候都存在一个很奇怪的现象:这两种集合的接口,Java 都为其设计了抽象类 Abstrac ...
- Java中的集合框架-Collection(二)
上一篇<Java中的集合框架-Collection(一)>把Java集合框架中的Collection与List及其常用实现类的功能大致记录了一下,本篇接着记录Collection的另一个子 ...
- JDK中日期和时间的几个常用类浅析(二)
java.util.Calendar JDK中的java.util.Calendar类主要是用来处理日期和时间相关的算法运算.当你需要做一些关于日期和时间的高级算数操作时,此类可能就是你的最好选择 ...
- JDK中String类的源码分析(二)
1.startsWith(String prefix, int toffset)方法 包括startsWith(*),endsWith(*)方法,都是调用上述一个方法 public boolean s ...
- 观察者模式--java jdk中提供的支持
一.简介 观察者设计模式有如下四个角色 抽象主题角色:把所有对观察者对象的引用保存在一个集合中,每个抽象主题角色都可以有任意数量的观察者.抽象主题提供一个接口,可以增加和删除观察者角色.一般用一个抽象 ...
随机推荐
- Android实例-获取安卓手机WIFI信息(XE8+小米2)
结果: 1.必须打开Access wifi state权限,不打开权限会出图二的错误. 相关资料: http://blog.csdn.net/lyf_lyf/article/category/1735 ...
- jq简单选项卡
function tabControl(obj,elm){ $(obj).hover(function(){ $(this).addClass('active').siblings().removeC ...
- Hibernate映射解析——七种映射关系
首先我们了解一个名词ORM,全称是(Object Relational Mapping),即对象关系映射.ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现,这样开发人员就可以把对 ...
- python的socket里 gethostbyname 与 gethostbyname_ex 的区别
python里有一个模块,叫socket,提供了BSD socket 的通信接口,在看了这个模块之后,我发现了两个很相似的函数------gethostbyname 和gethostbyname_ex ...
- C#不安全代码
当一个代码块使用 unsafe 修饰符标记时,C# 允许在函数中使用指针变量.不安全代码或非托管代码是指使用了指针变量的代码块. 下面的实例说明了不安全代码中的指针的定义与调用: static uns ...
- 一次线上OOM故障排查经过
转贴:http://my.oschina.net/flashsword/blog/205266 本文是一次线上OOM故障排查的经过,内容比较基础但是真实,主要是记录一下,没有OOM排查经验的同学也可以 ...
- cocos2d-x CCTableView
转自:http://www.cnblogs.com/dcxing/archive/2013/01/16/2862068.html CCTableView在游戏中一般用在背包这样场景或层中,当然也不止这 ...
- win7常用快捷键
Win+1:打开/显示超级任务栏第一个图标代表的程序Win+2:打开/显示超级任务栏第二个图标代表的程序(3.4.……如此类推)Win+Tab:3D切换窗口,你要是按住不松口,则所有窗口会轮流翻转Wi ...
- Codeforces Gym 100425A Luggage Distribution 二分 数学
A - Luggage DistributionTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudge/c ...
- JS调用Delphi编写的OCX控件
原文:http://www.mamicode.com/info-detail-471283.html 一.使用Delphi XE2编写OCX控件 生成OCX工程: 1.File-New-Other,在 ...