2. List(Collection的一个子接口——允许重复且有序)的新增的主要方法视图:
[java] view plaincopy
//1.在指定的位置上添加一个元素
public void add(int index, E element);
//2.取得指定位置上的元素
public E get(int index);
//3.修改指定位置上的元素,返回原先的元素
public E set(int index, E element);
//4.为ListIterator接口实例化
public ListIterator<E> listIterator();
//5.删除指定位置上的元素,返回删除的那个元素的引用
public E remove(int index);
2.1 新的子类:ArrayList
[java] view plaincopy
public class ArrayList<E> extends AbstractList<E>
implements List<E>,RandomAccess,Cloneable,Serializable
2.1.1 范例:设置内容
[java] view plaincopy
import java.util.ArrayList;
import java.util.List;
public class ArrayListDemo01 {
public static void main(String[] args) {
List<String> all = new ArrayList<String>(); // 实例化List接口
all.add("hello"); // 向集合中增加内容
all.add("world"); // 向集合中增加内容
all.add("!!!"); // 向集合中增加内容
for (int x = 0; x < all.size(); x++) {
System.out.println(all.get(x)) ;
}
}
}
说明:本例中使用List接口接收ArrayList实例,在取出数据的时候使用了List接口自己才有的get(int index)方法,如果使用Collection接收,取出数据时要先将其中的数据放到一个数组,然后从数组中取。如下例:
2.1.2 范例:Collection转换成数组输出
[java] view plaincopy
import java.util.ArrayList;
import java.util.Collection;
public class ArrayListDemo02 {
public static void main(String[] args) {
Collection<String> all = new ArrayList<String>(); // 实例化List接口
all.add("hello"); // 向集合中增加内容
all.add("world"); // 向集合中增加内容
all.add("!!!"); // 向集合中增加内容
all.remove("!!!"); // 从集合中删除指定对象
Object obj[] = all.toArray(); // 将所有的内容变为对象数组
for (int x = 0; x < obj.length; x++) {
String str = (String) obj[x];
System.out.print(str + "、");
}
}
}
说明:为了对输出数组的运行时类型进行更精确的控制,可以使用如下的方式来连接数组与集合。
2.1.3 范例:Collection转换成数组输出(精确控制数组类型)
[java] view plaincopy
import java.util.ArrayList;
import java.util.Collection;
public class ArrayListDemo02 {
public static void main(String[] args) {
Collection<String> all = new ArrayList<String>(); // 实例化List接口
all.add("hello"); // 向集合中增加内容
all.add("world"); // 向集合中增加内容
all.add("!!!"); // 向集合中增加内容
all.remove("!!!"); // 从集合中删除指定对象
Object obj[] = all.toArray(new String[]{}); // 将所有的内容变为对象数组
//或者Object obj[] = alll.toArray(new String[0]);
for (int x = 0; x < obj.length; x++) {
String str = (String) obj[x];
System.out.print(str + "、");
}
}
}
3. 不允许重复的子接口:Set
List接口中的内容是允许重复的,但是如果现在要求集合中的内容不能重复的话,就只能使用Set接口。Set接口不像List那样对Collection进行了大量的扩充,它对外的方法视图与Collection是完全一样的。
3.1 散列存放的子类:HashSet
[java] view plaincopy
public class HashSet<E>
extends AbstractSet<E>
implements Set<E>, Cloneable, Serializable
HashSet的定义方式和ArrayList很相似。
范例:添加元素与输出
[java] view plaincopy
import java.util.HashSet;
import java.util.Set;
public class HashSetDemo {
public static void main(String[] args) {
Set<String> all = new HashSet<String>();
all.add("hello");
all.add("hello"); // 重复设置
all.add("world");
all.add("!!!");
System.out.println(all) ;
}
}
说明:在Set接口中不允许有重复的元素存在,而且其中的元素是无序的,称为散列存放。
3.2 排序存放的子类:TreeSet
范例:排序存放
[java] view plaincopy
import java.util.Set;
import java.util.TreeSet;
public class TreeSetDemo {
public static void main(String[] args) {
Set<String> all = new TreeSet<String>();
all.add("B");
all.add("B");
all.add("X");
all.add("C");
all.add("A");
System.out.println(all);
}
}
说明:TreeSet不允许有重复内容,而且添加元素无序,输出时却是有序输出。
3.3 关于排序的补充
TreeSet中的元素对象可以排序要求它们实现Comparable接口,事先指定好排序规则。
范例:排序加入,compareTo()为0的对象元素将不会被再次添加
[java] view plaincopy
import java.util.Set;
import java.util.TreeSet;
class Person implements Comparable<Person> {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String toString() {
return "姓名:" + this.name + ",年龄:" + this.age;
}
@Override
public int compareTo(Person o) {
if (this.age < o.age) {
return 1;
} else if (this.age > o.age) {
return -1;
} else {
return this.name.compareTo(o.name);
}
}
}
public class SortDemo {
public static void main(String[] args) {
Set<Person> all = new TreeSet<Person>();
all.add(new Person("张三", 20));
all.add(new Person("李四", 20));
all.add(new Person("李四", 20));
all.add(new Person("王五", 19));
System.out.println(all);
}
}
3.4 关于重复元素的补充
Comparable可以完成TreeSet类中重复元素的判断,如果这种判断重复的方式通用的话,那么在HashSet中应该也能够使用。但是测试的结果否定了这样的猜测,Set中去掉重复元素的操作不是靠Comparable完成,它们靠两个方法来确定,这两个方法在Object中提供了定义:
[java] view plaincopy
public boolean equals(Object obj);
public int hashCode();
hashCode()可以为对象提供一个标示编号,如果要对对象内容进行验证需要重写equals()方法。hashCode()返回一个数字,它是通过特定的算法得到的,指定算法并不难,指定一个好的使同一个hashCode尽可能少地对应对象就需要花些心思了。
范例:重写hashCode()和equals()
[java] view plaincopy
import java.util.HashSet;
import java.util.Set;
class Person{
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.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;
Person other = (Person) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
public String toString() {
return "姓名:" + this.name + ",年龄:" + this.age;
}
}
public class RepeatDemo {
public static void main(String[] args) {
Set<Person> all = new HashSet<Person>();
all.add(new Person("张三", 20));
all.add(new Person("李四", 20));
all.add(new Person("李四", 20));
all.add(new Person("王五", 19));
System.out.println(all);
}
}
说明:JVM在管理众多的对象时,其底层实现采用的是一个大的哈希表,这个哈希表可能是用数组来模拟的,数组的下标是hashCode,在哈希表上每个值对应的是一个链表,链表中有哈希值相同的对象的引用。这样进行对象查找时就可以如同查字典一样,先计算对象的hashCode,这时的hashCode如果一个索引;然后迅速定位到索引所对应的对象链表,然后借助equals的内容比较方式进行属性的逐一比对以找到对应的对象。 |