java集合简介
java集合主要包括以下几点
- Java 集合概述
- Collection 接口
- Iterator 接口
- Set
- List
- Map
- Collections 工具类
- Enumeration
1.java集合概述

2.Collection 接口,Iterator接口
- public class TestCollection {
- public static void main(String[] args) {
- //1. 创建一个 Collection 接口的对象。接口对象,使用多态的方式.
- Collection collection = new ArrayList();
- //2. Collection 重要方法说明:
- /**
- * 2.1 用于添加元素的:
- * add():加入一个对象
- * addAll():加入一组对象
- */
- Person p1 = new Person();
- collection.add(p1);
- collection.add(new Person());
- Collection collection2 = new ArrayList();
- collection2.add(new Person());
- collection2.add(new Person());
- collection.addAll(collection2);
- System.out.println(collection.size());
- /**
- * 2.2 用于访问集合的方法:
- * size():获取集合的长度:
- * iterator():对集合进行遍历的方法,可以得到对应的 Iterator 接口对象.
- *
- * Iterator: 迭代器
- * ①. 获取 Iterator 接口对象:
- * ②. 使用 while 循环和 Iterator 对象遍历集合中的每一个元素. 具体使用 Iterator 接口的
- * hasNext() 和 next() 方法.
- */
- Iterator iterator = collection.iterator();
- while(iterator.hasNext()){
- Object obj = iterator.next();
- System.out.println(obj);
- }
- /**
- * 2.3 移除集合中的元素:
- * remove(): 移除某一个指定的对象. (API中)通过调用对象的 equals() 方法来判断要移除的那个元素在集合中是否存在. 以及是否能够成功移除.
- * 也就是说拿当前对象和集合中的对象一个个的比,如果有相同的equal返回true,就可以移除掉
- * 但是如果在Person里面重写了equals()方法,而且始终返回false,那么就永远也无法移出一个Person对象
- * removeAll():移出一组对象
- * clear(): 使集合中的元素置空.
- */
- collection.clear();
- boolean result = collection.remove(p1);
- System.out.println(result);
- result = collection.removeAll(collection2);
- System.out.println(collection.size());
- /**
- * 2.4 用于检测集合的方法
- * retains():是否包含一个对象
- * retainsAll():是否包含一个对象集合
- * isEmpty()
- *
- */
- System.out.println(collection.contains(new Person()));//false
- System.out.println(collection.contains(p1));//true
- System.out.println(collection.containsAll(collection2));//true
- System.out.println(collection.isEmpty()); //false
- collection.clear();
- System.out.println(collection.isEmpty()); //true
- /**
- * 2.5 其他方法
- * toArray(): 返回集合对应的数组对象
- * T [] toArray(T[]): 涉及到泛型(比如传入参数是一个Person对象数组,那么返回值也是一个Person对象数组)
- *
- * equals(): 比较两个集合是否相等.
- * 如果是ArrayList,不仅长度和每个对象都要一样,而且顺序也要一样,因为ArrayList是有顺序的
- * 对于HashSet就没有顺序要求
- * hasCode(): 返回集合的哈希码
- */
- Object [] objs = collection.toArray();
- System.out.println(objs.length); //
- Person p2 = new Person();
- Collection collection3 = new HashSet();
- collection3.add(p1);
- collection3.add(p2);
- Collection collection4 = new HashSet();
- collection4.add(p2);
- collection4.add(p1);
- System.out.println(collection3.equals(collection4));
- /**
- * 使用增强 for 循环的方式来对集合进行遍历
- */
- for(Object obj: collection){
- System.out.println(obj);
- }
- }
- }
3.Set
Set接口是Collection的子接口,所以前面讲的方法都可以用
Set中包含
- public static void main(String[] args) {
- Set set = new HashSet();
- //可以存放null
- set.add(null);
- System.out.println(set.size()); //1
- //存放同一个对象
- Person p1 = new Person();
- set.add(p1);
- set.add(p1);
- System.out.println(set.size()); //2
- //存放两个对象,当对象各个属性相同时,也要只存一次
- //这种情况必须重写待存入类Person类的hashCode和equals方法
- set.add(new Person("AA", 12));
- set.add(new Person("AA", 12));
- System.out.println(set.size()); //3
- //输出结果是不按顺序的
- set.add(new Person("FF", 13));
- Iterator it = set.iterator();
- while(it.hasNext()){
- System.out.println(it.next());
- }
- }
- public class Person {
- private String name;
- private int age;
- public Person(String name, int age) {
- super();
- this.name = name;
- this.age = age;
- }
- public Person() {
- super();
- }
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + age;
- result = prime * result + ((name == null) ? 0 : name.hashCode());
- return result;
- }
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- Person other = (Person) obj;
- if (age != other.age)
- return false;
- if (name == null) {
- if (other.name != null)
- return false;
- } else if (!name.equals(other.name))
- return false;
- return true;
- }
- }
Person类(重写了hashCode方法和equals方法)
Set的add方法时,调用了equals方法,查看是否有返回值为true的对象。同样,add方法同时也调用了hashCode,根据方法的返回的该对象的hashCode值来决定该对象的存储位置。
默认情况下,如果两个对象equals的返回值是true,那么对应的hashCode值一定相等。所以存储的位置是一样的,只能存一次。
- //根据对象的属性生成一个hashCode值
- //但是如果属性各个不相等,那么最后加起来可能就相等了
- //这里定义了prime这个素数来解决这个问题
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + age;
- result = prime * result + ((name == null) ? 0 : name.hashCode());
- return result;
- }
我们把它改成:
- private static int init = 0;
@Override- public int hashCode() {
- return init++;
- }
这样任何两个对象的hashCode都不会再相等了。hashSet将会把它们存储在不同的位置,依然可以添加成功(正常开发中不会出现这种情况)。
3.2 LinkedHashSet
- public static void main(String[] args) {
- Set set = new LinkedHashSet();
- set.add(null);
- Person p1 = new Person();
- set.add(p1);
- set.add(p1);
- set.add(new Person("AA", 12));
- set.add(new Person("AA", 12));
- set.add(new Person("FF", 13));
- Iterator it = set.iterator();
- while(it.hasNext()){
- System.out.println(it.next());
- }
- }
- //返回结果是 返回结果的顺序就是插入的顺序
- // null
- // com.atguigu.java.Person@3c1
- // com.atguigu.java.Person@d55
- // com.atguigu.java.Person@e14
3.3 TreeSet
- public class Person implements Comparable{
- private String name;
- private int age;
- public Person(String name, int age) {
- super();
- this.name = name;
- this.age = age;
- }
- public Person() {
- super();
- }
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + age;
- result = prime * result + ((name == null) ? 0 : name.hashCode());
- return result;
- }
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- Person other = (Person) obj;
- if (age != other.age)
- return false;
- if (name == null) {
- if (other.name != null)
- return false;
- } else if (!name.equals(other.name))
- return false;
- return true;
- }
- @Override
- public int compareTo(Object o) {
- if(o instanceof Person){
- Person stu = (Person) o;
- return this.age - stu.age;
- }else{
- throw new ClassCastException("不是一个Student对象. ");
- }
- }
- @Override
- public String toString() {
- return "Person [name=" + name + ", age=" + age + "]";
- }
- }
实现了Comparable接口的Person类
那么进行排序输出:
- public static void main(String[] args) {
- Set set = new TreeSet();
- set.add(new Person("AA", 98));
- set.add(new Person("BB", 50));
- set.add(new Person("CC", 95));
- System.out.println(set.size());
- for(Object obj: set){
- System.out.println(obj);
- }
- }
- //f返回值是:
- // 3
- // Person [name=BB, age=50]
- // Person [name=CC, age=95]
- // Person [name=AA, age=98]
默认是升序排序,如何倒序呢?
- //倒序:返回比较结果的相反数
- @Override
- public int compareTo(Object o) {
- if(o instanceof Person){
- Person stu = (Person) o;
- return -(this.age - stu.age);
- }else{
- throw new ClassCastException("不是一个Person对象. ");
- }
- }
如何根据name字段进行排序呢?
- //name排序:字符串已经实现了Compareable接口
- @Override
- public int compareTo(Object o) {
- if(o instanceof Person){
- Person stu = (Person) o;
- return this.name.compareTo(stu.name);
- }else{
- throw new ClassCastException("不是一个Person对象. ");
- }
- }
如果equals方法和comparableTo方法的返回值不一样,会出现怎么样的结果?
- public static void main(String[] args) {
- Set set = new TreeSet();
- set.add(new Person("AA", 98));
- set.add(new Person("BB", 90));
- set.add(new Person("CC", 95));
- set.add(new Person("DD", 98));
- System.out.println(set.size());
- for(Object obj: set){
- System.out.println(obj);
- }
- }
- //返回值是:
- // 3
- // Person [name=BB, age=90]
- // Person [name=CC, age=95]
- // Person [name=AA, age=98]
插入了四个对象,为什么才有三个成功呢?Person类里是重写了equals方法,而且实现了Comparable 接口 compareTo(Object obj) 方法,并按age字段排序。
当在添加元素时,从Set的角度,四个对象equals方法返回的值都不一样,都应该添加,但是从TreeSet的角度,它是排序添加,添加时第一个对象和第四个对象compareTo返回的值是相等的所以又不能添加了。
2.定制排序
- /**
- * 定制排序: 创建 TreeSet 对象时, 传入 Comparator 接口的实现类.
- * 要求: Comparator 接口的 compare 方法的返回值和 两个元素的 equals() 方法具有一致的返回值
- * @param args
- */
- public static void main(String[] args) {
- //创建一个内部类
- Comparator comparator = new Comparator() {
- @Override
- public int compare(Object o1, Object o2) {
- if(o1 instanceof Person && o2 instanceof Person){
- Person p1 = (Person) o1;
- Person p2 = (Person) o2;
- return p1.getAge() - p2.getAge();
- }else{
- throw new ClassCastException("不能转为 Person");
- }
- }
- };
- Set set2 = new TreeSet<>(comparator);
- set2.add(new Person("BB", 12));
- set2.add(new Person("CC", 16));
- set2.add(new Person("DD", 15));
- for(Object obj: set2){
- System.out.println(obj);
- }
- }
- //f返回值是:
- // 3
- // Person [name=BB, age=12]
- // Person [name=CC, age=15]
- // Person [name=AA, age=16]
4. List
http://www.cnblogs.com/tech-bird/p/3635032.html
4.1 ArrayList
ArrayList遍历的三种方式
- public static void main(String[] args) {
- List list = new ArrayList();
- list.add(new Person("AA", 12));
- list.add(new Person("BB", 13));
- list.add(new Person("CC", 14));
- list.add(new Person("DD", 15));
- //对 list 进行遍历
- Iterator it = list.iterator();
- while(it.hasNext()){
- System.out.println(it.next());
- }
- //使用 for 循环的方式对 list 进行遍历: 增强的 for 循环
- for(Object obj: list){
- System.out.println(obj);
- }
- //使用 for 循环的方式对 list 进行遍历: 使用 List 的 get(int) 方法
- for(int i = 0; i < list.size(); i++){
- System.out.println(list.get(i));
- }
- //使用ListIterator进行遍历(hasNext()和hasPrevious向后和向前)
- ListIterator lit = list.listIterator();
- while(lit.hasNext()){
- System.out.println(lit.next());
- }
- }
indexOf方法:获取一个元素在集合中的位置。那么首先得知道这个元素在集合中存在不存在,靠的是equals方法。
- public static void main(String[] args) {
- List list = new ArrayList();
- list.add(new Person("AA", 12));
- list.add(new Person("BB", 13));
- list.add(new Person("CC", 14));
- list.add(new Person("DD", 15));
- System.out.println(list.indexOf(new Person("BB", 13)));
- }
同前面讲的一样,必须让Person类重写equals方法,才能返回1,否则返回 -1
其他方法:
- public static void main(String[] args) {
- List list = new ArrayList();
- list.add(new Person("AA", 12));
- list.add(new Person("BB", 13));
- list.add(new Person("CC", 14));
- list.add(new Person("DD", 15));
- //把一个元素放到指定的位置
- list.add(2, new Person("EE", 16));
- //把一个元素加到末尾
- list.add(new Person("EE", 16));
- //获取指定元素在集合中的第一个位置
- System.out.println(list.indexOf(new Person("EE", 16))); //2
- //获取指定元素在集合中的最后一个位置
- System.out.println(list.lastIndexOf(new Person("EE", 16))); //5
- //相当于rePlace,把元素替换指定位置的元素
- list.set(3, new Person("AA", 12));
- //获取一个指定区间的集合(半闭半开区间)
- List list2 = list.subList(2, 5); //2, 3, 4
- }
- public static void main(String[] args) {
- System.out.println(Arrays.asList(new Person("MM", 23), new Person("NN", 24)));
- }
- }
- //f返回值是:
- // [Person [name=MM, age=23], Person [name=NN, age=24]]
集合和数组之间的转化:
1. public static <T> List<T> asList(T... a)
List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");
2. Object[] toArray() 或者 <T> T[] toArray(T[] a)
5.Map
- public interface Map<K,V> {
- //.....
- }
Map接口的方法:
- public static void main(String[] args) {
- //Map接口的典型实现是HashMap
- Map map = new HashMap();
- //1. 向 Map 中添加元素的:
- // put(key, value); 放入一个指定的键值对
- // put(map) 放入一组键值对
- map.put("AA", new Person("AA", 12));
- map.put("AA", new Person("AAA", 12)); //key值重复,会把上一个覆盖
- map.put("CC", new Person("CCC", 12));
- map.put("MM", new Person("MMM", 12));
- map.put("II", new Person("AAA", 12));
- //2. 从 Map 中取出元素的(遍历)
- //2.1 得到键的集合: keySet().
- Set keySet = map.keySet(); //用Set,不可重复
- for(Object key: keySet){
- //利用键得到值: get(key)
- Object value = map.get(key);
- System.out.println(key + ": " + value);
- }
- //2.2 直接得到 value 的集合
- Collection values = map.values(); //用Collection,可以重复
- System.out.println(values.getClass());
- for(Object val: values){
- System.out.println(val);
- }
- //2.3 得到 键值对的 集合(泛型)
- // 首先要把前面Map对象的定义改成 Map<String,Object> map = new HashMap<>();
- for(Map.Entry<String, Object> entry: map.entrySet()){
- String key = entry.getKey();
- Object val = entry.getValue();
- System.out.println(key + ": " + val);
- }
- //3. 移除元素的
- map.remove("AA");
- //4. 工具方法:
- //4.1 size() 方法
- System.out.println(map.size());
- System.out.println(map);
- //4.2 contains(); isEmpty()
- System.out.println(map.containsKey("BB"));
- System.out.println(map.isEmpty());
- }
HashMap和HashSet的关系
- public class HashSet<E>
- extends AbstractSet<E>
- implements Set<E>, Cloneable, java.io.Serializable
- {
- static final long serialVersionUID = -5024744406713321676L;
- private transient HashMap<E,Object> map;
- // Dummy value to associate with an Object in the backing Map
- private static final Object PRESENT = new Object();
- public Iterator<E> iterator() {
- return map.keySet().iterator();
- }
- public int size() {
- return map.size();
- }
- public boolean isEmpty() {
- return map.isEmpty();
- }
- public boolean contains(Object o) {
- return map.containsKey(o);
- }
- //............
- }
可以看出,在HashSet里面维护了一个HashMap对象,其中的Key值就是HashSet里的元素(无序,不重复),Value值是一个Object类型的常量。所以对HashSet的操作都是通过调用HashMap来实现的。
所以HashMap与HashSet相似之处
- Key值无序,不重复
- HashMap 可以使用 null 作为 key 和 value
- HashMap 判断两个 Key 相等的标准是:两个 Key 通过 equals 方法返回 true,hashCode 值也相等。
- HashMap 判断两个 Value相等的标准是:两个 Value 通过 equals 方法返回 true
5.2 HashTable
5.3 LinkedHashMap
- public LinkedHashSet() {
- super(16, .75f, true);
- }
- HashSet(int initialCapacity, float loadFactor, boolean dummy) {
- map = new LinkedHashMap<>(initialCapacity, loadFactor);
- }
- public TreeSet() {
- this(new TreeMap<E,Object>());
- }
比如:
- public static void main(String[] args) {
- Comparator comparator = new Comparator() {
- @Override
- public int compare(Object o1, Object o2) {
- Person p1 = (Person) o1;
- Person p2 = (Person) o2;
- return p1.getAge() - p2.getAge();
- }
- };
- TreeMap tm = new TreeMap(comparator);
- tm.put(new Person("AA", 12), "AAA");
- tm.put(new Person("BB", 22), "AAA");
- tm.put(new Person("CC", 2), "AAA");
- tm.put(new Person("DD", 9), "AAA");
- Set keySet = tm.keySet();
- for(Object key: keySet){
- Object val = tm.get(key);
- System.out.println(key + ": " + val);
- }
- }
- }
- //返回值是:
- //
- // Person [name=CC, age=2]: AAA
- // Person [name=DD, age=9]: AAA
- // Person [name=AA, age=12]: AAA
- // Person [name=BB, age=22]: AAA
5.5 Properties
属性(Properties)文件在Java 中对一个的是一个 Properties 类的对象
如何加载一个属性文件:
首先要new一个File,命名为 jdbc.properties,内容为:
- url=jdbc:mysql:///test
- driver=com.mysql.jdbc.Driver
- user=root
- password=1230
获取信息:
- public static void main(String[] args) throws Exception {
- /**
- * properties 文件在 Java 中对一个的是一个 Properties 类的对象
- */
- //1. 创建一个 Properties 类的对象
- Properties properties = new Properties();
- //2. 使用 IO 流加载对应的 properties 文件
- // 文件一定要和src同目录,否则要写全路径
- properties.load(new FileInputStream("jdbc.properties"));
- //3. 得到对应的属性值(通过键来获取值)
- String url = properties.getProperty("url");
- System.out.println(url);
- }
6.Collections 工具类
Collection是一个接口,而Collections 是一个操作 Set、List 和 Map 等集合的工具类(含有的工具方法全部都是静态方法)
static <T extends Object & Comparable<? super T>> T |
min(Collection<? extends T> coll)
Returns the minimum element of the given collection, according to the natural ordering of its elements.
|
static <T> T |
min(Collection<? extends T> coll, Comparator<? super T> comp)
Returns the minimum element of the given collection, according to the order induced by the specified comparator.
|
又比如这两个方法,都是获取集合中最小的元素,第一个方法要求 集合中的元素必须要实现Comparable接口,第二个要求集合本身实现了Comparator(利用内部类)
对List进行排序
- public static void main(String[] args) throws Exception {
- List list = new ArrayList();
- list.add(new Person("AA", 12));
- list.add(new Person("BB", 11));
- list.add(new Person("CC", 5));
- list.add(new Person("DD", 10));
- //使用 Collections 中的方法对 List 中的元素进行排序
- Collections.sort(list, new Comparator() {
- @Override
- public int compare(Object o1, Object o2) {
- Person p1 = (Person) o1;
- Person p2 = (Person) o2;
- return - p1.getAge() + p2.getAge();
- }
- });
- for(Object obj: list){
- System.out.println(obj);
- }
- }
同步控制方法:
前面说ArrayList是线程不安全的,那么可以把它变成安全的
List list = Collections.synchronizedList(new ArrayList<>());
这样得到的list对象就是线程安全的。(只要传入一个集合,出来的集合就是线程安全的)
同理,Set,Map,Collection都有类似的方法
- //获取线程安全的 List 对象, 使用 synchronizedList()
- List list2 = Collections.synchronizedList(new ArrayList<>());
当我们操作集合的时候,如果觉得需要什么方法,都可以到Collections 类中来找
7 .Enumeration
- //对 Enumeration 对象进行遍历: hasMoreElements() nextElement()
- Enumeration names = Collections.enumeration(list);
- while(names.hasMoreElements()){
- Object obj = names.nextElement();
- System.out.println(obj);
- }
使用的时候,不会创建一个Enumeration对象,而是根据一些API得到Enumeration对象,然后进行遍历
java集合简介的更多相关文章
- Java 集合简介 一
什么是集合? 集合就是由若干个确定的元素所构成的整体.例如,5只小兔构成的集合: 在数学中,我们经常遇到集合的概念.例如: ● 有限集合 ○ 一个班所有的同学构成的集合: ○ 一个网站所有的商品构成的 ...
- Java集合---简介
概念 集合可以理解为一个动态的对象数组,不同的是集合中的对象内容可以任意扩充.Java最基本的集合接口:Collection接口 集合的特点 性能高 容易扩展和修改 Collection的常用子类 L ...
- Java 集合系列(一)
Java集合系列文章将以思维导图为主要形式来展示知识点,让零碎的知识形成体系. 这篇文章主要介绍的是[Java 集合的基本知识],即Java 集合简介. 毕业出来一直使用 PHP 进行开发,对于大学所 ...
- Java集合容器简介
Java集合容器主要有以下几类: 1,内置容器:数组 2,list容器:Vetor,Stack,ArrayList,LinkedList, CopyOnWriteArrayList(1.5),Attr ...
- [转载]Java集合容器简介
Java集合容器主要有以下几类: 1,内置容器:数组 2,list容器:Vetor,Stack,ArrayList,LinkedList, CopyOnWriteArrayList(1.5),Attr ...
- Java从零开始学二十(集合简介)
一.为什么需要集合框架 数组的长度是固定的,但是如果写程序时并不知道程序运行时会需要多少对象.或者需要更复杂的方式存储对象,---那么,可以使用JAVA集合框架,来解决这类问题 二.集合框架主要接口 ...
- Java连载81-枚举类型,生成五个不重复的随机数,集合简介
一.枚举类型 1.枚举类型的格式就是enum+枚举类型的名称,可见下面的例子. package com.bjpowernode.java_learning; public class D81_1_ ...
- Java 集合系列04之 fail-fast总结(通过ArrayList来说明fail-fast的原理、解决办法)
概要 前面,我们已经学习了ArrayList.接下来,我们以ArrayList为例,对Iterator的fail-fast机制进行了解.内容包括::1 fail-fast简介2 fail-fast示例 ...
- Java集合源码分析(四)Vector<E>
Vector<E>简介 Vector也是基于数组实现的,是一个动态数组,其容量能自动增长. Vector是JDK1.0引入了,它的很多实现方法都加入了同步语句,因此是线程安全的(其实也只是 ...
随机推荐
- codevs3008加工生产调度(Johnson算法)
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> us ...
- Java编程思想-泛型-简单泛型例子
基本类型无法做为类型参数 代码如下: /** * */ package test.thinkinjava.Generics; import java.util.ArrayList; import ja ...
- c# 用正则表达式获取开始和结束字符串中间的值
c# 用正则表达式获取开始和结束字符串中间的值 /// <summary> /// 获得字符串中开始和结束字符串中间得值 /// </summary> /// <para ...
- 抓取锁的sql语句-第四次修改
--完成情况 变量V_BLOCKING_SID 用来动态抓取 产生锁的会话id,输出参数没有任何问题,但是执行报错 标识符无效! CREATE OR REPLACE PROCEDURE SOLV ...
- Xcode6中如何修改文件中自动创建的Created by和Copyright
转自: http://blog.csdn.net/bjourney/article/details/46832159 在Xcode6创建问的时候,会自动生成注释 // Created byxxx o ...
- UIView之常用属性
UIView之常用属性 1. view.tag = 200; // 系统保留0-1002. view.frame = CGRectMake(20, 30, 300, 300);3. view.cent ...
- 你好,C++(9)坐216路公交车去买3.5元一斤的西红柿——C++中如何表达各种数值数据 3.3 数值数据类型
3.3 数值数据类型 从每天早上睁开眼睛的那一刻开始,我们几乎每时每刻都在与数字打交道:从闹钟上的6点30分,到上班坐的216路公共汽车:从新闻中说的房价跌到了100元每平米到回家买菜时的西红柿3. ...
- 【NEERC 2003】有向图破坏
[题目描述] Alice和Bob正在玩如下的游戏.首先Alice画一个有N个顶点,M条边的有向图.然后Bob试着摧毁它.在一次操作中他可以找到图中的一个点,并且删除它所有的入边或所有的出边. Alic ...
- 【USACO 1.2.1】挤牛奶
[问题描述] 三个农民每天清晨5点起床,然后去牛棚给3头牛挤奶.第一个农民在300时刻(从5点开始计时,秒为单位)给他的牛挤奶,一直到1000时刻.第二个农民在700时刻开始,在 1200时刻结束.第 ...
- 修改一行SQL代码 性能提升了N倍
在PostgreSQL中修改了一行不明显的代码,把(ANY(ARRAY[...]) 改成 ANY(VALUES(...))),结果查询时间从20s变为0.2s.最初我们学习使用EXPLAN ANALY ...