1.1 List
1.1.1 遍历ArrayList
package com.test;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class ArrayListDemo {
public static void main(String args[]){
List list = new ArrayList();
list.add("test");
list.add("demo");
//方法1
Iterator it1 = list.iterator();
while(it1.hasNext()){
System.out.println(it1.next());
}
//方法2
for(Iterator it2 = list.iterator();it2.hasNext();){
System.out.println(it2.next());
}
//方法3
for(String tmp:list){
System.out.println(tmp);
}
//方法4
for(int i = 0;i < list.size(); i ++){
System.out.println(list.get(i));
}
}
}
1.1.2 数组与List之间相互转换的方法详解
- List转换成为数组(这里的List是实体是ArrayList)
调用ArrayList
的toArray
方法。
public T[] toArray(T[] a)
返回一个按照正确的顺序包含此列表中所有元素的数组;返回数组的运行时类型就是指定数组的运行时类型。如果列表能放入指定的数组,则返回放入此列表元素的数组。否则,将根据指定数组的运行时类型和此列表的大小分配一个新的数组。
如果指定的数组能容纳列表并有剩余空间(即数组的元素比列表的多),那么会将数组中紧跟在集合末尾的元素设置为null
。这对确定列表的长度很有用,但只在调用方知道列表中不包含任何null
元素时才有用。
指定者:接口Collection
中的toArray
指定者:接口List
中的toArray
覆盖:类AbstractCollection
中的toArray
参数:a - 要存储列表元素的数组,如果它足够大的话;否则,它是一个为存储列表元素而分配的、具有相同运行时类型的新数组。
返回:包含列表元素的数组。
抛出:ArrayStoreException - 如果 a 的运行时类型不是此列表中每个元素的运行时类型的超类型
具体用法:
List list = new ArrayList();
list.add("1");
list.add("2");
final int size = list.size();
String[] arr = (String[])list.toArray(new String[size]);
- 数组转换成为List
调用Arrays
的asList
方法.
JDK 1.4
对java.util.Arrays.asList
的定义,函数参数是Object[]
。所以,在1.4
中asList()
并不支持基本类型的数组作参数。
JDK 1.5
中,java.util.Arrays.asList
的定义,函数参数是Varargs
, 采用了泛型实现。同时由于autoboxing
的支持,使得可以支持对象数组以及基本类型数组。
不过在使用时,当传入基本数据类型的数组时,会出现小问题,会把传入的数组整个当作返回的List中的第一个元素,例如:
public static void main(String[] args){
int[] a1 = new int[]{1,2,3};
String[] a2 = new String[]{"a","b","c"};
System.out.println(Arrays.asList(a1));
System.out.println(Arrays.asList(a2));
}
1
2 [[I@dc8569]
[a, b, c]
下面说说Arrays.asList()
的返回值:
JDK
文档是这么说的:
public static
返回一个受指定数组支持的固定大小的列表。(对返回列表的更改会List asList(T... a) 直接写
到数组。)此方法同Collection.toArray()
一起,充当了基于数组的API
与基于collection
的API
之间的桥梁。返回的列表是可序列化的,并且实现了RandomAccess
。此方法还提供了一个创建固定长度的列表的便捷方法,该列表被初始化为包含多个元素:List
stooges = Arrays.asList("Larry", "Moe", "Curly");
/**
* @serial include
*/
private static class ArrayListextends AbstractListimplements RandomAccess, java.io.Serializable {
private static final long serialVersionUID = -2764017481108945198L;
private final E[] a;
ArrayList(E[] array) {
if (array == null)
throw new NullPointerException();
a = array;
}
public int size() {
return a.length;
}
public Object[] toArray() {
return a.clone();
}
public T[] toArray(T[] a) {
int size = size();
if (a.length < size)
return Arrays.copyOf(this.a, size, (Class extends T[]>) a.getClass());
System.arraycopy(this.a,0, a, 0, size);
if (a.length > size)
a[size] = null;
return a;
}
public E get(int index) {
return a[index];
}
public E set(int index, E element) {
E oldValue = a[index];
a[index] = element;
return oldValue;
}
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i < a.length; i++)
if (a[i] == null)
return i;
}else {
for (int i = 0; i < a.length; i++)
if (o.equals(a[i]))
return i;
}
return -1;
}
public boolean contains(Object o) {
return indexOf(o) != -1;
}
}
我们都知道,List
的一个典型的特性就是其长度是可变的,我们可以很方便地对它进行插入和删除元素的操作,这是它与数组所存在的一个很大的区别,后者的长度是固定的,而且我们不能从数组中删除元素,只能修改元素的值。利用Arrays.asList(array)
将返回一个List
,然而这个返回的List
并不支持add
和remove
的操作。这是什么原因呢?
Arrays.asList源码:
public static List asList(T... a) {
return new ArrayList(a);
}
这里的ArrayList
并不是java.util.ArrayList
,而是Arrays
的内部类:
我们可以看到该内部类继承的是AbstractList
,下面是AbstractList
的add
和remove
方法源码:
public boolean add(E e) {
add(size(), e);
return true;
}
public void add(int index, E element) {
throw new UnsupportedOperationException();
}
public E remove(int index) {
throw new UnsupportedOperationException();
}
所以,当我们对Arrays.asList
返回的List
进行添加或删除时将会报 java.lang.UnsupportedOperationException
异常。
1.2 遍历Map
1.2.1 四种遍历Map方法
- 利用
Map. keyset
方法。 在map
中方法定义如下:
Set keySet();
例如:
for (String stuKey : stuMap.keySet()) {
stuStr = stuKey;
stu = stuMap.get(stuKey);
}
- 只能遍历
values
用到方法是Map.values
for (Student student : stuMap.values()) {
stu = student;
}
- 利用
Map.Keyset().iterator()
方法。
Iterator> it = stuMap.entrySet().iterator();
ile (it.hasNext()) {
Map.Entry entry = it.next();
stuStr = entry.getKey();
stu = entry.getValue();
}
- 结合
Map.Entry
和entry entrySet
方法:
for (Map.Entry entry : stuMap.entrySet()) {
stuStr = entry.getKey();
stu = entry.getValue();
}
1.2.2 分析四种方法性能
首先创建了一个测试内为: student
,如下:
public class Student {
private int age;
private String name;
public Student(String name, int age) {
this.age = age;
this.name = name;
}
}
主类:
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class MapListor {
private static Map stuMap = new HashMap ();
public static void main(String[] args) {
intMap(200);
//method 1: Map.Keyset()
long endTime = 0;
String stuStr = ""; // key used to be set when listing map.
Student stu = null; // value used to be set when listing map.
long startTime = System.currentTimeMillis();
for (String stuKey : stuMap.keySet()) {
stuStr = stuKey;
stu = stuMap.get(stuKey);
}
endTime = System.currentTimeMillis();
System.out.println("Using the first method to list Map("+ stuMap.size()+") costs: " + (endTime - startTime) );
//method 2: Map.Keyset().iterator()
startTime = System.currentTimeMillis();
Iterator> it = stuMap.entrySet().iterator();
while (it.hasNext()) {
Map.Entry entry = it.next();
stuStr = entry.getKey();
stu = entry.getValue();
}
endTime = System.currentTimeMillis();
System.out.println("Using the second method to list Map("+ stuMap.size()+") costs: " + (endTime - startTime) );
//method 3: Map.Entry entry and entrySet method.
startTime = System.currentTimeMillis();
for (Map.Entry entry : stuMap.entrySet()) {
stuStr = entry.getKey();
stu = entry.getValue();
}
endTime = System.currentTimeMillis();
System.out.println("Using the third method to list Map("+ stuMap.size()+") costs: " + (endTime - startTime) );
//method 4: only list values.
for (Student student : stuMap.values()) {
stu = student;
}
}
/**
* init the stuMap according to the input number of students.
* @param stuNumber
*/
private static void intMap(int stuNumber) {
Student stu = null;
for (int i = 0; i < stuNumber; i++) {
stu = new Student("student" + i, (int)Math.random() * 100);
stuMap.put(String.valueOf(i), stu);
}
}
}
1.3 Set
1.3.1 HashSet
java
中Set
集合是一个不包含重复元素的Collection
,首先我们先看看遍历方法
package com.sort;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
/**
* 一个不包含重复元素的 collection。更确切地讲,set 不包含满足 e1.equals(e2) 的元素对 e1 和 e2,
* @author Owner
*
*/
public class SetTest2 {
public static void main(String[] args) {
Set set = new HashSet();
set.add("a");
set.add("b");
set.add("c");
set.add("d");
set.add("e");
set.add("e");//不能放入重复数据
/**
* 遍历方法一,迭代遍历
*/
for(Iterator iterator = set.iterator();iterator.hasNext();){
System.out.print(iterator.next()+" ");
}
System.out.println();
System.out.println("********************");
/**
* for增强循环遍历
*/
for(String value : set){
System.out.print(value+" ");
}
}
}
注意:这里Set
集合中放入的是String
类型,假如我们放入一个自己定义的类实例的时候,比如Person
类实例,这时候我们要自己重新hashcode
和equal
方法,用自己的关键字段来重写,因为当使用HashSet
时,hashCode()
方法就会得到调用,判断已经存储在集合中的对象的hash code
值是否与增加的对象的hash code
值一致;如果不一致,直接加进去;如果一致,再进行equals
方法的比较,equals
方法如果返回true
,表示对象已经加进去了,就不会再增加新的对象,否则加进去。
1.3.1 TreeSet
TreeSet
使用元素的自然顺序
对元素进行排序,或者根据创建 set
时提供的 Comparator
进行排序,具体取决于使用的构造方法。
通俗一点讲,就是可以按照排序后的列表显示,也可以按照指定的规则排序
Set set = new TreeSet();
set.add("f");
set.add("a");
set.add("b");
set.add("c");
set.add("d");
set.add("e");
System.out.println(set);
输出:[a, b, c, d, e, f]
那么如果我们想让他倒序输出呢?当然方法很多。这里我采用指定一个规则让他倒序输出
package com.sort;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;
public class TreeSetTest3 {
public static void main(String[] args) {
Set set = new TreeSet(new MyComparator());
set.add("a");
set.add("b");
set.add("c");
set.add("d");
set.add("e");
set.add("A");
for(Iterator iterator = set.iterator();iterator.hasNext();){
System.out.print(iterator.next()+" ");
}
}
}
class MyComparator implements Comparator{
@Override
public int compare(String o1, String o2) {
return o2.compareTo(o1);//降序排列
}
}
输出:e d c b a A
如果Set
集合中放入的是我们自己定义的一个类类型呢?
注意:一定要定义一个排序规则类实现Comparator
接口,与上面的方法类似
package com.sort;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;
public class TreeSetTest2 {
public static void main(String[] args) {
Set set = new TreeSet(new PersonComparator());
Person p1 = new Person(10);
Person p2 = new Person(20);
Person p3 = new Person(30);
Person p4 = new Person(40);
set.add(p1);
set.add(p2);
set.add(p3);
set.add(p4);
for(Iterator iterator = set.iterator();iterator.hasNext();){
System.out.print(iterator.next().score+" ");
}
}
}
class Person{
int score;
public Person(int score){
this.score = score;
}
public String toString(){
return String.valueOf(this.score);
}
}
class PersonComparator implements Comparator{
@Override
public int compare(Person o1, Person o2) {
return o1.score - o2.score;
}
}
输出:10 20 30 40
如果按照一个人的分数的倒序排列,只需要更改compare方法中的o2.score-o1.score