在java开发中,会使用到集合框架的许多接口来提高开发效率,使用较多的包括Collection(集合)
Map(图),Comparator(比较器),Iterator(迭代器)等常用的接口。
Collection中包括List和Set两种常用实现类,List可以存储重复的元素,但Set不行
List分为ArrayList和LinkedList等实现类。
Set包含HashSet和TreeSet等实现类。
Map包含HashMap和TreeMap等实现类
这些接口的使用需要自己熟练掌握常用的API。
ArrayList
ArrayList与数据结构中的线性表类似,顺序存储元素
当向表中1位置插入刘六时,李四和王五后移。
同理,删除某个位置上的元素时,后面的元素前移。
代码
List list=new ArrayList();
list.add("张三");
list.add("李四");
list.add("王五");
list.add(1,"刘六");
list.remove(1);
LinkedList
LinkedList与数据结构中的双向链表类似,元素存储的位置随机。
id value previous next 0 1 张三 header 45 … 45 李四 1 76 … 76 王五 76 tail
在张三和李四中间添加刘六,只需要在链表任意位置存储一个刘六,让张三的next
指向他,他的next指向李四,previous指向张三,李四的previous指向刘六,就可以了。
id value previous next 0 1 张三 header 65 … 45 李四 45 76 … 65 刘六 1 45 … 76 王五 76 tail
代码,删除操作可以从下往上看表格就明白了
List list=new LinkedList();
list.add("张三");
list.add("李四");
list.add("王五");
list.add(1,"刘六");
list.remove(1);
ArrayList与LinkedList的比较
ArrayList对于遍历和查找表中的元素是友好的,一般用于展示表中存储的内容
LinkedList对于增加删除操作的友好的,一般用于频繁的增删操作。
泛型的使用
泛型与C++中的函数模板类似
泛型的使用将程序运行时可能产生的异常转移到了程序编译时就可以发现,极大的提高了
程序的健壮性。举个例子
import java. util. list
public class Test {
public static void main ( String[ ] args) {
List personList= new ArrayList ( ) ;
Person person = new Person ( ) ;
Tiger tiger= new Tiger ( ) ;
personList. add ( person) ;
personList. add ( tiger) ;
for ( int i= 0 ; i< personList. size; i++ ) {
Person per = ( Person) personList. get ( i)
per. hello;
}
}
}
class Tiger { }
class Person {
public void hello ( ) {
System. out. println ( "hello" ) ;
}
}
使用泛型,让list只能存放Person类型的元素,如果存放其他类型的元素,则编译器报错。
import java. util. list
public class Test {
public static void main ( String[ ] args) {
List< Person> personList= new ArrayList < Person> ( ) ;
Person person = new Person ( ) ;
Tiger tiger= new Tiger ( ) ;
personList. add ( person) ;
for ( int i= 0 ; i< personList. size; i++ ) {
Person per = personList. get ( i)
per. hello;
}
}
}
class Tiger { }
class Person {
public void hello ( ) {
System. out. println ( "hello" ) ;
}
}
泛型一般在集合中使用,可以统一集合中的数据类型,减少强制类型转换。
如果不使用泛型,那么在遍历集合时需要大量的强制类型转换,甚至直接报错。
泛型还有很多没有介绍的机制,这里介绍了常用的一种,有兴趣可以深入了解。
HashSet
HashSet的存储类似与Map的存储包括key和value,是利用hash函数分配的存储空间。
当要遍历set中的数据时,发现没有set.get(index)这个API,那么该如何遍历。有如下方法。
在涉及到对象是否重复的时候需要用到hashcode()和equals()两个Object下的非final方法,
也就是要重写这两个方法。以后会专门写一篇文章来介绍,这里不做过多介绍。
import java. util. list
public class Test {
public static void main ( String[ ] args) {
Set< String> set= new HashSet < String> ( ) ;
set. add ( "Alice" ) ;
set. add ( "Blice" ) ;
set. add ( "Clice" ) ;
Iterator< String> itor= set. iterator ( ) ;
while ( itor. hasNext) {
String str= itor. next ( ) ;
Syetem. out. println ( str) ;
}
}
Iterator
Iterarator是Collection下的一个接口。
使用时注意遍历的顺序是根据hash值来决定打印顺序,而不是存储的顺序。
Iterarator的原理和单向链表类似.
Iterarator可以在很多地方使用。
一般使用方法:
Iterator< String> itor= set. iterator ( ) ;
while ( itor. hasNext) {
String str= itor. next ( ) ;
Syetem. out. println ( str) ;
}
TreeSet
TreeSet和HashSet都是Set下的一个接口。
TreeSet与HashSet最大的区别在于TreeSet中的元素是有序的。
默认字母串按26字母排序,数字按大小排序。
注意汉字并不一定是安装拼音排序,但目前已经有了相应的算法
Comparable
在使用TreeSet时,如果使用自定义的类型进行存储则会报错,因为TreeSet中并没有自定义
的排序方法,所以这个时候需要在自定义类型中重写Comparable接口下的compareTo方法
举个例子
public class Person implements Comparable < Person> {
private String name;
private int age;
private String address;
@Override
public int commpareTo ( Person person) {
if ( this . age> person. getAge ( ) ) {
return 1 ;
} else if ( this . age> person. getAge ( ) ) {
return - 1 ;
}
return 0 ;
}
}
public class Test {
public static void main ( String[ ] args) {
Person p1= new Person ( "张三" ,23 , "中国" ) ;
Person p2= new Person ( "李四" ,19 , "印度" ) ;
Set< Person> persons= new TreeSet < Person> ( ) ;
person. add ( p1) ;
person. add ( p2) ;
Iterator< Person> itor= persons. iterator ( ) ;
for ( ; itor. hasNext; ) {
Syetem. out. println ( itor. next) ;
}
}
}
Comparator
因为commparable的排序规则单一,只能使用一种排序方法,如果想要使用其他的排序方法,
需要重新重写CommpareTo方法,代码的维护代价增加。
不在Person类中重写CommpareTo方法,而是创建一个比较器类来实现java.util包下的Comparator
方法。然后再需要使用的地方new一个比较器。将这个比较器丢到TreeSet中就可以进行比较。
如果需要不同的比较器可以再创建一个比较器,使用哪个比较器new哪个比较器。
举个例子
public class Person {
private String name;
private int age;
private String address;
}
public class Desccomparator ( Person o1, Person o2) {
if ( o1. age> o2. age) {
return - 1 ;
} else if ( o1. age> o2. age) {
return 1 ;
}
return 0 ;
}
public class Asccomparator ( Person o1, Person o2) {
if ( o1. age> o2. age) {
return 1 ;
} else if ( o1. age> o2. age) {
return - 1 ;
}
return 0 ;
}
public class Test {
public static void main ( String[ ] args) {
Person p1= new Person ( "张三" ,23 , "中国" ) ;
Person p2= new Person ( "李四" ,19 , "印度" ) ;
Comparetor comparetor= new Desccomparetor ( ) ;
Set< Person> persons= new TreeSet < Person> ( comparetor) ;
person. add ( p1) ;
person. add ( p2) ;
Iterator< Person> itor= persons. iterator ( ) ;
for ( ; itor. hasNext; ) {
Syetem. out. println ( itor. next) ;
}
}
}
HashMap
一个最贴近的生活例子就是超市的储物箱,当你存放东西(value)的时候,会给你一个纸条(key)
当你拿会自己的东西(value)时,只要根据纸条(key)就可以了。
下面直接用代码演示一下用法
public class Test {
public static void main ( String[ ] args) {
Map< String, String> map= new HashMap < String, String> ( ) ;
map. put ( "k001" , "张三的水" ) ;
map. put ( "k002" , "李四的包" ) ;
map. put ( "k003" , "王五的帽子" ) ;
System. out. println ( map. size ( ) ) ;
Set< String> keys= map. keySet ( ) ;
Iterator itor= keys. iterator ( ) ;
while ( itor. hasNext) {
String key= itor. next ( ) ;
String value= map. get ( key) ;
Syetem. out. println ( key+ "---->" + value) ;
}
}
}
其他的用法需要查看API文档。
TreeMap
和TreeSet一样,TreeMap也是可以根据key默认排序的。
在给自定义类型排序时,因为没有排序方法,所以会报错,这个时候就需要重写commpareTo
方法或者新建比较器。
一般key不会采用自定义的类型。这里不再演示比较器的创建使用。可参见TreeSet
public class Test {
public static void main ( String[ ] args) {
Map< String, String> map= new TreeMap < String, String> ( ) ;
map. put ( "k003" , "张三的水" ) ;
map. put ( "k001" , "李四的包" ) ;
map. put ( "k002" , "王五的帽子" ) ;
System. out. println ( map. size ( ) ) ;
Set< String> keys= map. keySet ( ) ;
Iterator itor= keys. iterator ( ) ;
while ( itor. hasNext) {
String key= itor. next ( ) ;
String value= map. get ( key) ;
Syetem. out. println ( key+ "---->" + value) ;
}
}
k001-- -- > 李四的包
k002-- -- > 王五的帽子
k003-- - > 张三的水
}
Tips
List允许重复,具有下标索引,get(Index),remove(index);
Set不允许重复,没有下标索引,remove(obj);
HashSet比较对象用hashcode()和equals()
TreeSet比较对象用commpareTo或者比较器