活动地址:CSDN21天学习挑战赛
3. 集合框架
3.1 简介
绿色为接口,蓝色为实现类:
Iterable
:可使用for-each
进行迭代
Collection
:常规的集合CRUD
操作
3.2 Iterable
要使用增强版的for
循环,即for-each
,必须实现该接口:
public class GenericList<T> implements Iterable<T> {
private T[] items = (T[]) new Object[8];
private int count;
public void add(T item) {
items[count++] = item;
}
public T get(int index) {
return items[index];
}
@Override
public Iterator<T> iterator() {
return new ListIterator<>();
}
private class ListIterator<T> implements Iterator<T> {
private int index;
@Override
public boolean hasNext() {
return index < count;
}
@Override
public T next() {
return (T) items[index++];
}
}
}
public class Main {
public static void main(String[] args) {
var list = new GenericList<String>();
list.add("a");
list.add("b");
var iterator = list.iterator();
// while (iterator.hasNext()){
// var current = iterator.next();
// System.out.println(current);
// }
for (var item : list) {
System.out.println(item);
}
}
}
3.3 Collection
Collection
接口包含了操作一个集合的基本动作,即CRUD
:
public class CollectionsDemo {
public static void show() {
Collection<String> collection = new ArrayList<>();
collection.add("a");
collection.add("b");
collection.add("c");
Collections.addAll(collection, "x", "y", "z");
for (var item : collection)
System.out.println(item);
var arr = collection.toArray(new String[0]);
System.out.println(arr.length);
collection.remove("c");
System.out.println(collection);
System.out.println(collection.contains("a"));
collection.clear();
System.out.println(collection);
System.out.println(collection.isEmpty());
Collection<String> other = new ArrayList<>();
other.addAll(collection);
System.out.println(collection == other);
System.out.println(collection.equals(other));
}
}
3.4 List
List
,有序列表,插入的元素是按照放入的顺序排列的,可以根据索引进行访问。
public class ListDemo {
public static void show() {
List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add(0, "x");
System.out.println(list.get(0));
list.set(0, "!");
System.out.println(list);
list.remove(0);
System.out.println(list);
System.out.println(list.indexOf("c"));
System.out.println(list.subList(0, 2));
}
}
3.5 排序
方案1:使用Comparable
public class SortDemo {
public static void show(){
List<Customer> list = new ArrayList<>();
list.add(new Customer("b"));
list.add(new Customer("c"));
list.add(new Customer("a"));
Collections.sort(list);
System.out.println(list);
}
}
public class Customer implements Comparable<Customer> {
private String name;
public Customer(String name) {
this.name = name;
}
@Override
public int compareTo(Customer o) {
return name.compareTo(o.name);
}
@Override
public String toString() {
return "Customer{" +
"name='" + name + '\'' +
'}';
}
}
上述方案不太灵活,主要由于负责比较的逻辑与Customer
这个类绑定(耦合)在一起,一旦这个类封装好以后,如果比较规则改变(例如按照年龄进行比较),需要重新定义逻辑并且重新编译。
方案2:使用Comparator
public class NameComparator implements Comparator<Customer> {
@Override
public int compare(Customer o1, Customer o2) {
return o1.getName().compareTo(o2.getName());
}
}
public class SortDemo {
public static void show(){
List<Customer> list = new ArrayList<>();
list.add(new Customer("b"));
list.add(new Customer("c"));
list.add(new Customer("a"));
Collections.sort(list, new NameComparator());
System.out.println(list);
}
}
该方案的好处在于,负责比较的逻辑与实体类的定义是分离的(解藕),我们可以很方便的添加多个负责比较的Comparator
实现,而无需修改实体类的定义。
3.6 Queue
Queue
,队列,遵循FIFO
(First In First Out,先进先出原则),常用来处理多任务。
public class QueueDemo {
public static void show(){
Queue<String> queue = new ArrayDeque<>();
queue.add("a");
queue.add("b");
queue.offer("c");
var front = queue.peek();// element()
System.out.println(front);
System.out.println(queue);
front = queue.poll();// remove()
System.out.println(front);
System.out.println(queue);
}
}
3.7 Set
Set
,实现该接口的集合不允许有重复元素,且并不保证有序。
public class SetDemo {
public static void show(){
Set<String> set = new HashSet<>();
set.add("sky");
set.add("is");
set.add("blue");
set.add("blue");
System.out.println(set);
Collection<String> collection = new ArrayList<>();
Collections.addAll(collection,"a","b","b");
set = new HashSet<>(collection);
System.out.println(set);
Set<String> s1 = new HashSet<>(Arrays.asList("a","b","c"));
Set<String> s2 = new HashSet<>(Arrays.asList("b","c","d"));
// //Union
// s1.addAll(s2);
// System.out.println(s1);
// //Intersection
// s1.retainAll(s2);
// System.out.println(s1);
//Difference
s1.removeAll(s2);
System.out.println(s1);
}
}
3.8 Map
public class MapDemo {
public static void main(String[] args) {
List<Customer> list = new ArrayList<>();
//O(n) -> O(10)
for(var customer : list){
if(customer.getName().equals("xxx"))
System.out.println("Find!");
}
}
}
在上述案例中,我们需要从一个集合中查询一个指定姓名的Customer
对象,如果这个查询的复杂度记为O(n)
,即如果集合的大小为10,那么耗费的时间为O(10)
,可以理解为查询所耗费的时间是直接与集合的大小有关的一个结果。
上述分析,考虑的是最差的情况,也即是要查询的目标有可能是集合的最后一个元素。
public class MapDemo {
public static void main(String[] args) {
var c1 = new Customer("a");
var c2 = new Customer("b");
Map<String, Customer> map = new HashMap<>();
map.put(c1.getName(),c1);
map.put(c2.getName(),c2);
var c = map.get("a"); //getOrDefault()
System.out.println(c);
var exists = map.containsKey("a");
System.out.println(exists);
map.replace("a", new Customer("x"));
System.out.println(map);
for(var key : map.keySet()){
System.out.println(key + ":" +map.get(key));
}
for(var entry : map.entrySet()){
System.out.println(entry.getKey() + ":" + entry.getValue());
}
for(var customer : map.values()){
System.out.println(customer);
}
}
}