-
常用容器
其中Vector是线程安全的,而Collection线程不安全。线程安全的效率也低。 -
泛型
数据类型的参数化。数据类型的一个占位符(形参)。告诉编译器,在调用泛型时必须传入实际类型。一般使用<T,E,V>三个字母。
- 取消了强制类型转换
- 编译期类型检查
泛型的上下界
- 上界
谁(?)是Person的子类(extends),谁就可以使用该泛型定义的方法。含Person。
public static void print(ArrayList<? extends Person> a1){
...
}
- 下界
谁(?)是Student的父类(super),谁就可以使用该泛型定义的方法。含Student。
public static void show(ArrayList<? super Student> a1){
......
}
- TreeMap的使用
在有排序需求的时候使用。底层使用红黑树组织数据。
import java.util.Map;
import java.util.TreeMap;
public class Test1 {
public static void main(String[] args) {
Map<Integer, String> treemap1 = new TreeMap<>();
treemap1.put(30, "张飞");
treemap1.put(20, "吕布");
treemap1.put(10, "关羽");
// 按key递增的方式排序
for (int key : treemap1.keySet()) {
System.out.println(treemap1.get(key));
}
Map<Stuff, String> treemap2 = new TreeMap<>();
treemap2.put(new Stuff(56, "赵云", 8000), "怀抱阿斗者");
treemap2.put(new Stuff(31, "诸葛亮", 3000), "运筹帷幄");
treemap2.put(new Stuff(10, "刘备", 5000), "中山晋王之后");
treemap2.put(new Stuff(16, "孙夫人", 5000), "赔了夫人又折兵");
// 按key递增的方式排序
for (Stuff key : treemap2.keySet()) {
System.out.println(key + " " + treemap2.get(key));
}
}
}
class Stuff implements Comparable<Stuff> {
int id;
String name;
double salary;
public Stuff(int id, String name, double salary) {
this.id = id;
this.name = name;
this.salary = salary;
}
@Override
public String toString() {
return "(id=" + id + ",name=" + name + ",salary=" + salary + ")";
}
@Override
public int compareTo(Stuff o) {
if (salary > o.salary) {
return 1;
} else if (salary < o.salary) {
return -1;
} else {
if (id > o.id) {
return 1;
} else if (id < o.id) {
return -1;
} else {
return 0;
}
}
}
}
- HashMap与HashTable的区别
- HashMap:线程不安全,效率高。允许key或者value为null。
- HashTable :线程安全,效率低。不允许key或者value为null。
- Set接口
-
Set容器特点:无序、不可重复。无序指Set中的元素没有索引,我们只能遍历查找;不可重复指不允许加入重复的元素。更确切地讲,新元素如果和Set中某个元素通过equals()方法对比为true,则不能加入;甚至,Set中也只能放入一个null元素,不能多个。
-
HashSet底层也是由HashMap实现的。当然TreeSet底层也是由TreeMap实现的。
-
注意:
TreeMap是对key排序,而TreeSet是对元素排序。自定义对象的排序规则时,TreeMap是对key(对象)实现Comparable接口重写compareTo()方法;而TreeSet是对元素(对象)实现Comparable接口重写compareTo()方法。这里的Comparable接口是提供内部比较器的方式,还可以提供外部比较器——即实现Comparator接口重写compare()方法。其中字符串String的比较可以借助compareTo()方法。 -
在HashSet中存放POJO:
必须重写hashCode()方法及equals()方法。
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = 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;
}
/**
* HASH表的存储原理(存储为顺序表+链表。顺序表根据装填因子
* (load_factor=loaded_element_no/list.length)调整扩容减少冲突
* (load_factor>=0.75就扩容顺序表list),
* 链表长度>=8后采用红黑树(一种平衡二叉树,优化查找次数)存储数据并优化查找。)
* 1. 调用hashCode()计算HASH值
* 2. 根据哈希函数计算存储位置
* 3. 如果存储位置上没有元素则存储之
* 4. 否则要调用equals()比较内容是否相同(冲突处理时调用)
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
System.out.println("调用hashCode():"+result);
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
System.out.println("调用equals():true");
return true;
}
if (obj == null) {
System.out.println("调用equals():false");
return false;
}
if (getClass() != obj.getClass()) {
System.out.println("调用equals():false");
return false;
}
Person other = (Person) obj;
if (age != other.age) {
System.out.println("调用equals():false");
return false;
}
if (name == null) {
if (other.name != null) {
System.out.println("调用equals():false");
return false;
}
} else if (!name.equals(other.name)) {
System.out.println("调用equals():false");
return false;
}
System.out.println("调用equals():true");
return true;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
测试
public class Test01 {
public static void main(String[] args) {
Set<Person> hs=new HashSet<>();
Person p1=new Person("林冲",31);
Person p2=new Person("宋江",41);
Person p3=new Person("林冲",31);
Person p4=new Person("李逵",28);
hs.add(p1);
hs.add(p2);
hs.add(p3);
hs.add(p4);
System.out.println(hs);
}
}
输出
调用hashCode():844925
调用hashCode():756460
调用hashCode():844925
调用equals():true
调用hashCode():858572
[Person{name='林冲', age=31}, Person{name='李逵', age=28}, Person{name='宋江', age=41}]
- 对TreeSet使用外部比较器
外部比较器的优势在于可以随意定义多个,在TreeSet构造对象时通过传参自由决定使用什么比较器(比较规则)。
public class Test02 {
public static void main(String[] args) {
Comparator<Person> cmp=new MyComparator();
TreeSet<Person> ts=new TreeSet<>(cmp);
Person p1=new Person("酒保",18);
Person p2=new Person("宋江",41);
Person p3=new Person("酒保",30);
Person p4=new Person("李逵",28);
ts.add(p1);
ts.add(p2);
ts.add(p3);
ts.add(p4);
System.out.println("集合元素个数:"+ts.size());
System.out.println(ts);
}
}
class MyComparator implements Comparator<Person> {
@Override
public int compare(Person o1, Person o2) {
Person p1 = (Person) o1;
Person p2 = (Person) o2;
if (p1.getName().compareTo(p2.getName()) > 0) {
return -1;
} else if (p1.getName().compareTo(p2.getName()) < 0) {
return 1;
} else {
return p1.getAge() - p2.getAge();
}
}
}
- 迭代器
提供统一的方式来遍历List/Set/Map。
- 迭代器遍历List
public class Test {
public static void main(String[] args) {
List<String> aList = new ArrayList<String>();
for (int i = 0; i < 5; i++) {
aList.add("a" + i);
}
System.out.println(aList);
for (Iterator<String> iter = aList.iterator(); iter.hasNext();) {
String temp = iter.next();
System.out.print(temp + "\t");
if (temp.endsWith("3")) {// 删除3结尾的字符串
iter.remove();
}
}
System.out.println();
System.out.println(aList);
}
}
- 迭代器遍历Set
public class Test {
public static void main(String[] args) {
Set<String> set = new HashSet<String>();
for (int i = 0; i < 5; i++) {
set.add("a" + i);
}
System.out.println(set);
for (Iterator<String> iter = set.iterator(); iter.hasNext();) {
String temp = iter.next();
System.out.print(temp + "\t");
}
System.out.println();
System.out.println(set);
}
}
- 迭代器遍历Map
//方式一:
public class Test {
public static void main(String[] args) {
Map<String, String> map = new HashMap<String, String>();
map.put("A", "高淇");
map.put("B", "高小七");
Set<Entry<String, String>> ss = map.entrySet();
//增强for循环
for(Entry<String, String> en : ss) {
System.out.println(en.getKey() + "\t" + en.getValue());
}
//for (Iterator<Entry<String, String>> iterator = ss.iterator(); iterator.hasNext();) {
// Entry<String, String> e = iterator.next();
// System.out.println(e.getKey() + "--" + e.getValue());
//}
}
}
//方式二:
public class Test {
public static void main(String[] args) {
Map<String, String> map = new HashMap<String, String>();
map.put("A", "高淇");
map.put("B", "高小七");
Set<String> ss = map.keySet();
//增强for循环
for(String key : ss) {
System.out.println(key + "\t" + map.get(key));
}
//for (Iterator<String> iterator = ss.iterator(); iterator.hasNext();) {
// String key = iterator.next();
// System.out.println(key + "--" + map.get(key));
//}
}
}
- 使用while循环遍历一般用于一边遍历一边添加/删除的方式。但需要使用ListIterator迭代器。ListIterator是Iterator迭代器的扩展,不仅支持正向遍历,还支持反向遍历。更重要的是可以一边遍历一边添加/删除容器内容。这种功能如果使用Iterator和容器对象实现会报ConcurrentModificationException异常。
ArrayList<String> a1 = new ArrayList<>();
a1.add("西门吹雪");
a1.add("叶孤城");
a1.add("陆小凤");
ListIterator<String> lit = a1.listIterator();
//遍历过程中动态添加元素
while (lit.hasNext()) {
String str = lit.next();
if ("陆小凤".equals(str)) {
lit.add("花满楼");
}
}
System.out.println(lit);
//逆向遍历
while (lit.hasPrevious()) {
System.out.println(lit.previous());
}
- java.util.Collections工具类
类 java.util.Collections 提供了对Set、List、Map进行排序、填充、查找元素的辅助方法。
- void sort(List) //对List容器内的元素排序,排序的规则是按照升序进行排序。
- void shuffle(List) //对List容器内的元素进行随机排列。
- void reverse(List) //对List容器内的元素进行逆续排列 。
- void fill(List, Object) //用一个特定的对象重写整个List容器。
- int binarySearch(List, Object)//对于顺序的List容器,采用折半查找的方法查找特定对象。
public class Test {
public static void main(String[] args) {
List<String> aList = new ArrayList<String>();
for (int i = 0; i < 5; i++){
aList.add("a" + i);
}
System.out.println(aList);
Collections.shuffle(aList); // 随机排列
System.out.println(aList);
Collections.reverse(aList); // 逆续
System.out.println(aList);
Collections.sort(aList); // 排序
System.out.println(aList);
System.out.println(Collections.binarySearch(aList, "a2"));
Collections.fill(aList, "hello");
System.out.println(aList);
}
}
- 通过容器来实现ORM(Object Record Mapping)
可以使用List/Set/Map灵活组合实现ORM。
- 通过List+Map实现ORM
// Map是键值对的集合
Map<String, Object> row1 = new HashMap<>();
row1.put("id", 10);
row1.put("name", "周伯通");
row1.put("salary", 11000);
row1.put("age", 27);
Map<String, Object> row2 = new HashMap<>();
row2.put("id", 13);
row2.put("name", "紫衫龙王");
row2.put("salary", 28997);
row2.put("age", 27);
Map<String, Object> row3 = new HashMap<>();
row3.put("id", 21);
row3.put("name", "黄蓉");
row3.put("salary", 65243);
row3.put("age", 27);
Map<String, Object> row4 = new HashMap<>();
row4.put("id", 5);
row4.put("name", "郭靖");
row4.put("salary", 33526);
row4.put("age", 27);
// List是Map的集合
List<Map<String, Object>> table = new ArrayList<>();
table.add(row1);
table.add(row2);
table.add(row3);
table.add(row4);
for (Map<String, Object> row : table) {
Set<String> cols = row.keySet();
for (String col : cols) {
System.out.print(col + ":" + row.get(col) + "\t");
}
System.out.println();
}
System.out.println("-------------------------------------");
for (Map<String, Object> row : table) {
Set<String> cols = row.keySet();
for (Iterator<String> it = cols.iterator(); it.hasNext();) {
String col = it.next();
System.out.print(col + ":" + row.get(col) + "\t");
}
System.out.println();
}
- 通过JavaBean/POJO+List实现ORM
public class Test {
public static void main(String[] args) {
List<Staff> staffs = new ArrayList<>();
staffs.add(new Staff(1, "貂蝉", 8746, 18));
staffs.add(new Staff(2, "西施", 7736, 22));
staffs.add(new Staff(3, "王昭君", 8765, 27));
staffs.add(new Staff(4, "杨玉环", 7876, 30));
for (Iterator<Staff> it = staffs.iterator(); it.hasNext();) {
System.out.println(it.next());
}
}
}
/**
* JavaBean
*
* @author beeworkshop
*
*/
class Staff {
private int id;
private String name;
private int salary;
private int age;
// 一个完整的JavaBean需要有getter和setter方法,还要有一个空的无参构造器。
// 一个JavaBean对应数据库表的一行/记录。
public Staff() {
}
public Staff(int id, String name, int salary, int age) {
super();
this.id = id;
this.name = name;
this.salary = salary;
this.age = age;
}
@Override
public String toString() {
return "[id=" + id + ", name=" + name + ", salary=" + salary + ", age=" + age + "]";
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}