目录
概览
说明:
- 集合框架是一个类库的集合,里面还有很多接口。里面虚框都是接口。
- 全部在java.util
- HashSet是基于HashMap实现的。
- TreeSet是一个有序Set。
- ArrayList能快速随机访问,可变大小。
- LinkedList随机访问相对慢,但是可以当作stack或者queue来用。
Collection接口常用方法
public void contextLoads() {
ArrayList list1 = new ArrayList();
ArrayList list2 = new ArrayList();
list1.add("one");
list1.add(2); // 没有指定集合的数据类型,也不会报错
list2.addAll(list1);
list2.add(3.14);
Iterator it1 = list2.iterator(); // 获取迭代器
while (it1.hasNext()) { // 迭代器是否有下一个?
System.out.print(it1.next() + " "); // 迭代器指向的值
} // one 2 3.14
list2.remove(1); // 按index
list2.removeAll(list1); // 删掉list1中有的元素
System.out.println("delete list1, size: " + list2.size()); // 大小
}
ArrayList类
下面是List接口常用的方法:
使用的时候直接:
List<String> li = new ArrayList<String>();
- 指定元素类型比较好。因为不指定的话,默认是Object类型,那么get()返回的也是Object,还要转换成期望的数据类型。
- 这里其实是使用接口List,引用了一个ArratList实例。
- 这里指定类型,其实用到了Java提供的泛型特性。泛型可以在编译的时候检查类型安全,并且自动隐式转换一些类型。比如:使用Map的get()方法,这里隐式转换为Book类型,由于Book里重写了public String toString(),所以可以直接打印想要的格式。
Map<Integer,Book> books=new HashMap<Integer,Book>(); //定义泛型 Map 集合
System.out.println(books.get(id));
LinkedList类
- 采用链表结构保存对象,所以适合频繁插入删除元素时使用。
- 随机访问会慢。
- 具有Collection接口和List接口提供的方法。
set
遍历:
Set<Integer> set;
Iterator<Integer> iterator = set.iterator();
while (iterator.hasNext()) {
iterator.next();
}
for (int item : set) {
System.out.println(item);
}
HashSet类
- 向Set集合中添加新元素时,HashSet会调用该元素的hashCode()方法,获取哈希码,根据哈希码计算出元素在集合中的存储位置。
- 后添加的相同元素会覆盖前一个。就算是null,也只能有一个。
- HashSet也实现了Collection接口!里面的方法都可以用!
TreeSet类
- 只能对实现了Comparable接口的类对象进行排序。
- 升序
- 要使用排序功能,需要添加相同数据类型的对象,不然抛出ClassCastException 异常。
- 除了Collection接口的方法外,还有:
HashMap
- HashMap按照哈希算法存取对象,TreeMap则是对key进行了排序,方法是一样的。
- Map接口常用方法
Map<Integer, StringBuilder> m = new HashMap<>();
m.put(j, m.get(j).append(temp.charAt(j)));
// 不用先删除再add
HashMap<String, String> users=new HashMap<String, String>();
users.put("11","张浩太"); //将学生信息键值对存储到Map中
users.put("22","刘思诚");
users.put("33","王强文");
users.put("44","李国量");
users.put("55","王路路");
Scanner input=new Scanner(System.in);
System.out.println("请输入要删除的学号:");
int num=input.nextInt();
if(users.containsKey(String.valueOf(num))) {
users.remove(String.valueOf(num)); // 以key删除一个元素
} else {
System.out.println("该学生不存在!");
}
System.out.println("******** 学生列表 ********");
Iterator it=users.keySet().iterator(); // 使用迭代器
while(it.hasNext()) {
String key = (String)it.next(); // it.next()返回的是Object,需要强制转换
String val = users.get(key);
System.out.println("学号:"+key+",姓名:"+val);
}
// 遍历Map
Map<String, String> map = new HashMap<String, String>();
//第三种:推荐,尤其是容量大时
System.out.println("通过Map.entrySet遍历key和value");
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
}
如果遍历时需要同时取出key和val,那么尽量用entrySet()代替先取key再查val(尤其是key比较复杂的时候)
Collection常用算法
Collections.sort(名称):升序排序
Collections.reverse(名称):反转
Collections.copy(destList,srcList):复制
如果destList长度不够,IndexOutOfBoundsException;长度够的话,复制到开头,剩余元素不影响。
Collections.fill(List<? super T> list,T obj) //使用指定元素替换指定列表中的所有元素
泛型
除去Collection对泛型的支持(指定数据类型后编译时自动转换),另外还有泛型类和泛型方法。
泛型类
public class class_name<data_type1,data_type2,…>{
private data_type1 name1;
}
实例
public class Stu<N,A,S> {
private N name;
private A age;
private S sex;
public Stu(N name, A age, S sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
//下面是上面3个属性的setter/getter方法
// 就是记住全部用声明里指出的类型来代替。就好像Template
}
Stu<String, Integer, Character> stu = new Stu<String, Integer, Character>("Ann", 30, '女'); // Integer才是类,int是基本数据类型
String name=stu.getName();
Integer age=stu.getAge();
Character sex=stu.getSex();
System.out.println("学生姓名:"+name+",年龄:"+age+",性别:"+sex);
泛型方法
- 泛型方法可以独立于类产生变化。泛型方法所在的类不一定是泛型类。如果使用泛型方法就可以取代类的泛型化,那么就应该只使用泛型方法。
- static方法无法访问泛型类的类型参数(N,A,S这些),也就是说,泛型类里static方法是很难用的,所以如果static方法需要泛型能力,就必须变成泛型方法。
[访问权限修饰符][static][final]<类型参数列表>返回值类型 方法名([形式参数列表])
高级用法
- 限制泛型可用类型
Java默认是可以使用任何类型来实例化一个泛型对象的,但是也可以限制能用泛型的类型
class 类名称<T extends anyClass>
比如:
public class ListClass<T extends List> {
}
// 在main中测试:
ListClass<ArrayList> lc1 = new ListClass<ArrayList>();
ListClass<LinkedList> lc2=new ListClass<LinkedList>();
ListClass<HashMap> lc3=new ListClass<HashMap>();
// 这个HashMap没有实现List接口,所以这个实例化会报错
- 使用类型通配符
语法:泛型类名称<? extends List>a=null;
A<? extends List>a=null;
a=new A<ArrayList> (); //正确
b=new A<LinkedList> (); //正确
c=new A<HashMap> (); //错误
- 继承泛型类和实现泛型接口
定义为泛型的类可以被继承,如果要保留父类的泛型类型,需要在继承时指定。而且泛型父类不能强制转换成泛型子类,因为子类需要的类型并没有被填满。
public class FatherClass<T1>{}
public class SonClass<T1,T2,T3> extends FatherClass<T1>{}
可以在泛型中实现接口:
interface interface1<T1>{}
interface SubClass<T1,T2,T3> implements Interface1<T2>{}
枚举
JDK1.5之前没有enum,一般用接口常量替代。
语法:
[public|private|internal] enum 名称[:基础类型]
{
枚举成员; // 不能重名,常数值必须在基础类型之内,多个用逗号分隔
}
如果没有显示声明基础类型,那么基础类型就是int
使用时:枚举类型名称.枚举成员名称
枚举类
- 枚举类继承自java.lang.Enum。
- 定义一个枚举类型时,每个成员都可以看作Enum类的实例。
public class DbApplicationTests {
enum Signal
{
GREEN, YELLOW, RED;
}
public void compare(Signal s) {
for (Signal i: Signal.values()) { // 返回枚举类型所有值
System.out.println(s+"比较"+i+":"+s.compareTo(i));
// 返回索引差值,找不到的抛异常
} // i.ordinal()可以获取索引值
}
@Test
public void contextLoads() {
try {
compare(Signal.valueOf("RED"));
// 把普通字符串转为枚举实例
/*
* RED比较GREEN:2 实际就是2-0
* RED比较YELLOW:1
* RED比较RED:0
*/
compare(Signal.valueOf("BLUE")); // 找不到哦
} catch(IllegalArgumentException e) {
System.out.println(e);
/*
* java.lang.IllegalArgumentException:
* No enum constant com.example.demo.DbApplicationTests.Signal.BLUE
*/
}
}
}
枚举类里面也可以添加方法,就类似普通类。
java.util中还有EnumMap和EnumSet。
//定义数据库类型枚举
public enum DataBaseType
{
MYSQL,ORACLE,DB2,SQLSERVER
}
//某类中定义的获取数据库URL的方法以及EnumMap的声明
private EnumMap<DataBaseType,String>urls=new EnumMap<DataBaseType,String>(DataBaseType.class);
public DataBaseInfo()
{
urls.put(DataBaseType.DB2,"jdbc:db2://localhost:5000/sample");
urls.put(DataBaseType.MYSQL,"jdbc:mysql://localhost/mydb");
urls.put(DataBaseType.ORACLE,"jdbc:oracle:thin:@localhost:1521:sample");
urls.put(DataBaseType.SQLSERVER,"jdbc:microsoft:sqlserver://sql:1433;Database=mydb");
}
//根据不同的数据库类型,返回对应的URL
//@param type DataBaseType 枚举类新实例
//@return
public String getURL(DataBaseType type) {
return this.urls.get(type);
}