集合框架

Java是面向对象编程,万事万物皆“对象”,为了方便对“对象”进行操作,需要对“对象”进行存储,而Java集合就是存储“对象”的容器,可以动态地把多个对象存入容器中。Java集合类可以用于存储数量不等的多个对象,还可以用于保存具有映射关系的关联数组。

Collection接口

  • 单列集合,用来存储”一个一个“的对象。

  • 向Collection接口的实现类的对象添加数据(obj)时,要求obj所在的类重写equals()。(不重写的话Collection中有些方法的判断会有影响。)

  • Collection接口中的方法:

  1. add(Object obj):添加一个对象。
  2. addAll(Collection coll):添加一个集合。
  3. int size():获取集合内有效元素的个数。
  4. void clear():清空集合。
  5. boolean isEmpty():判断集合是否为空。
  6. boolean contains(Object obj):判断集合中是否包含obj对象。(调用equals()进行判断)
  7. boolean containsAll(Collection coll):判断集合中是否包含coll集合内的所有对象。(调用equals()进行判断)
  8. boolean remove(Object obj):删除集合中第一个与obj对象相同的对象元素。(调用equals()进行判断)
  9. boolean removeAll(Collection coll):取当前集合与coll集合的差集。
  10. boolean retainAll(Collection coll):取当前集合与coll的交集。
  11. boolean equals(Object obj):判断集合是否相等。(注意有序性和无序性)
  12. hashCode():获取集合对象的哈希值。
  13. Object[] toArray():将集合转换成Object类型数组。(调用Arrays.asList(),可以把数组转换成集合)
  14. iterator():返回迭代器对象,用于集合的遍历。

迭代器使用注意点:(迭代器是设计模式中的一种)

Collection接口实现了java.lang.Iterable接口,该接口中有iterator(),所有实现了Collection接口的实现类都有一个iterator()方法。

  1. 集合对象每次调用iterator(),都会得到一个全新的迭代器对象,默认游标在第一个元素之前。
  2. Iterator仅用于遍历集合,Iterator本身并不提供承装对象的能力。
  3. 迭代器中的重要的两个方法:hasNext()和next()。
  4. hasNext()判断是否还有下一个元素。
  5. 调用next()后,迭代器游标下移,并返回下移之后集合位置上对应的元素。如果没有使用hasNext()判断下一条记录是否有效,且下一条记录无效,调用next()后,则抛出异常(NoSuchElementException)。
  6. 迭代器也可以删除集合中的元素,调用的是迭代器中的remove(),不是集合的remove()。
  7. 如果没有调用next()或在上一次调用next()方法后已经调用了remove(),再次调用remove()都会抛出异常(IllegalStateException)。

迭代器遍历集合示例:

@Testpublic void test3(){Collection c = new ArrayList();c.add(123);c.add(3.14);c.add('A');Iterator iterator1 = c.iterator();while (iterator1.hasNext()) {System.out.println(iterator1.next());}System.out.println("=========================================");Iterator iterator2 = c.iterator();while (iterator2.hasNext()){Object o = iterator2.next();if (o.equals(123)){iterator2.remove();}}Iterator iterator3 = c.iterator();while(iterator3.hasNext()){System.out.println(iterator3.next());}}

List接口

  • 存放的对象特点:有序,可重复。
  • List接口下有三个实现类:ArrayList、LinkedList、Vector。

List接口中新提供的方法:

  1. void add(int index,Object obj):在下标为index位置插入obj元素。
  2. boolean addAll(int index,Collection coll):从下标为index处,将集合coll所有的元素添加进来。
  3. Object get(int index):获取下标为index的元素。
  4. int indexOf(Object obj):返回obj对象在当前集合第一次出现的位置下标。
  5. int lastIndexOf(Object obj):返回obj对象在当前集合最后一次出现的位置下标。
  6. Object remove(int index):删除index位置对应的元素,并返回该元素。(注意区分Collection接口下的remove())
  7. Object set(int index,Object obj):设置指定index位置的元素为obj。
  8. List subList(int fromIndex,int toIndex):返回从fromIndex到toIndex位置的子集合。

ArrayList

  • 适用于经常需要进行查询操作的对象集合。

  • JDK1.7及1.2之前,new ArrayList();创建ArrayList对象,底层就创建了长度为10的Object[]数组elementData。JDK1.8后,new ArrayList();创建ArrayList对象,底层Object[] elementData初始化为{},并没有创建长度为10的数组,直到ArrayList对象第一次调用add()时,才创建长度为10的数组,并把add()的参数添加到数组中。

  • 底层为用Object[] elementData数组进行存储。不带参数的构造方法创建的ArrayList对象默认容量为10(initialCapacity),也可以使用带参构造方法创建ArrayList的对象,创建的时候就指定容量。

  • 扩容:变为原来的1.5倍(原容量加上原容量右移1位,即1+(1/2)),并把原数组的元素复制到新数组中。

  • 查询效率高;插入、删除效率低。

Arrays.asList()使用注意点

    //asList()注意点@Testpublic void test2(){Collection coll = new LinkedList();coll.add(123);List list1 = Arrays.asList(new int[]{1, 2, 3, 4, 5, 6, 7});// 不自动装箱的话把整个int[]当成一个对象System.out.println(list1.size());   //1// 需要手动装箱List list2 = Arrays.asList(new Integer[]{1,2,3,4,5,6,7});System.out.println(list2.size());   //7System.out.println(list2);}

LinkedList

  • 使用于经常需要插入和删除操作的对象集合。

  • 底层用双向链表进行存储,没有定义数组,定义了Node类型的first和last记录首末元素,同时定义内部类Node,作为LinkedList中保存数据的基本结构,还定义了两个变量prev和next,分别记录前一个和后一个元素的位置。

Vector

线程安全,效率低,底层使用Objece[] elementData数组进行存储。

在JDK1.7和1.8中通过Vector()构造器创建对象时,底层都创建了长度为10的数组。在扩容方面,默认扩容为原来数组的两倍。


Set接口

  • 存放对象的特点:无序(存入和取出的顺序可能不一致),不可重复,如果尝试添加两个相同的元素,则添加操作失败。
  • Set接口下的实现类有:HashSet,LinkedHashSet,TreeSet。
  • Set接口没有提供额外的方法,所以用的都是Collection接口中的方法。
  • Set中的元素判断两个对象是否相同用的是equals(),而不是“==”。
  • 对于存放在Set容器中的对象:一定要重写hashCode()和equals(),以实现对象相等规则,即相等的对象必须具有相等的散列码(哈希值)。

重写hashCode()的原则:

  1. 程序运行时,同一个对象多次调用hashCode()应该返回相同的值。
  2. 当两个对象的equals()比较返回true时,两个对象的hashCode()返回值也应该相同。
  3. 对象中用作equals()方法比较的属性,都应该用来计算hashCode值。
  4. hashCode()的默认行为是对堆上的对象产生独特值,如果没有重写hashCode(),则该class的两个对象的hashcode无论如何都不会相等,即使这两个对象的数据相同。

重写equals()的原则:

  1. 当一个类有自己特有的“逻辑相等”概念,当改写equals()的时候,总是要改写hashCode(),根据一个类改写后的equals(),两个截然不同的对象有可能在逻辑上是相等的,但是根据Object.hashCode(),他们仅仅是两个对象,因此违反了“相等的对象必须具有相等的散列码”。
  2. 重写equals()方法的时候一般需要重写hashCode(),通常参与计算hashCode的对象的属性也应该参与到equals()中进行计算。

HashSet

  • HashSet底层实现是:HashMap。底层存储结构是数组,初始容量为16,扩容为原来的2倍。
  • 不能保证元素的排列顺序。(不意味着每次遍历集合,对象的顺序都会改变)
  • HashSet不是线程安全的。
  • 可以存储null值。

示例:

@Test
public void test1(){HashSet set = new HashSet();set.add(123);set.add(456);set.add("abc");set.add(null);set.add(5858);set.add(5858);System.out.println(set);}

LinkedHashSet

  • LinkedHashSet底层实现是:LinkedHashMap。

  • LinkedHashSet不是线程安全的。

  • LinkedHashSet是HashSet的子类。

  • 以元素插入的顺序来维护集合的链表。

  • LinkedHashSet类里面添加了两个引用,用来记录当前元素的前一个元素和后一个元素(双向链表),因此LinkedHashSet可以按照元素添加的前后顺序遍历集合中所有的元素(这并不意味着有序性)。

  • 对于频繁遍历操作,LinkedHashSet的效率高于HashSet。插入元素的性能略低于HashSet。

  • 可以存储null值。

示例:

@Test
public void test1(){LinkedHashSet set = new LinkedHashSet();set.add(123);set.add(456);set.add("abc");set.add(null);System.out.println(set);
}

TreeSet

  • TreeSet底层实现是:红黑树。
  • 只能存储相同类型的引用类型数据。
  • 有两种排序方式,自然排序和定制排序(涉及Comparable和Comparator),默认情况下为自然排序。
  • TreeSet不是线程安全的。
  • 不可以存储null值,会抛出异常(NullPointException)。

示例:TreeSet按照两种排序存储数据。

Employee类:实现了Comparable接口。

/*** @Author:xiezr* @Creat:2021-07-14 20:57*/
public class Employee implements Comparable {private String name;private int age;private MyDate birthday;public Employee() {}public Employee(String name, int age, MyDate birthday) {this.name = name;this.age = age;this.birthday = birthday;}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;}public MyDate getBirthday() {return birthday;}public void setBirthday(MyDate birthday) {this.birthday = birthday;}@Overridepublic String toString() {return "Employee{" +"name='" + name + '\'' +", age=" + age +", birthday=" + birthday +'}' +'\n';}// 按名称从低到高排序,再按年龄从高到低排序@Overridepublic int compareTo(Object o) {if (o instanceof Employee){Employee e1 = (Employee) o;if (this.name.equals(e1.name)){return -this.age - e1.age;}else {return this.name.compareTo(e1.name);}}throw new RuntimeException("输入的类型错误!");}
}

MyDate类:无实现Comparable或Comparator接口。

/*** @Author:xiezr* @Creat:2021-07-14 20:57*/
public class MyDate {private int year;private int month;private int day;public MyDate() {}public MyDate(int year, int month, int day) {this.year = year;this.month = month;this.day = day;}public int getYear() {return year;}public void setYear(int year) {this.year = year;}public int getMonth() {return month;}public void setMonth(int month) {this.month = month;}public int getDay() {return day;}public void setDay(int day) {this.day = day;}@Overridepublic String toString() {return "MyDate{" +"year=" + year +", month=" + month +", day=" + day +'}';}
}

测试:

import org.junit.Test;import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;/*** @Author:xiezr* @Creat:2021-07-14 21:17*/
public class TreeSetTest {// 按名称从低到高排序,再按年龄从高到低排序@Testpublic void test1(){Employee e1 = new Employee("Adel", 25, new MyDate(1998, 8, 31));Employee e2 = new Employee("Maroon5",35,new MyDate(1987,6,6));Employee e3 = new Employee("LinKinPark",28,new MyDate(1999,2,9));Employee e4 = new Employee("Passenger",27,new MyDate(1999,5,6));Employee e5 = new Employee("Eminem",40,new MyDate(1979,2,6));Employee e6 = new Employee("Adel", 52, new MyDate(1945, 8, 31));TreeSet treeSet = new TreeSet();treeSet.add(e1);treeSet.add(e2);treeSet.add(e3);treeSet.add(e4);treeSet.add(e5);treeSet.add(e6);System.out.println(treeSet);}// 按照出生年份从大到小排,月份天数从小到大排@Testpublic void test2(){Employee e1 = new Employee("Adel", 25, new MyDate(1998, 8, 31));Employee e2 = new Employee("Maroon5",35,new MyDate(1987,6,6));Employee e3 = new Employee("LinKinPark",28,new MyDate(1999,2,9));Employee e4 = new Employee("Passenger",27,new MyDate(1999,2,6));Employee e5 = new Employee("Eminem",40,new MyDate(1979,2,6));Employee e6 = new Employee("Adel", 52, new MyDate(1945, 8, 31));TreeSet treeSet = new TreeSet(new Comparator() {@Overridepublic int compare(Object o1, Object o2) {if (o1 instanceof Employee && o2 instanceof Employee){Employee e1 = (Employee) o1;Employee e2 = (Employee) o2;MyDate m1 = e1.getBirthday();MyDate m2 = e2.getBirthday();int minusYear = m1.getYear() - m2.getYear();if (minusYear != 0){return -minusYear;}else {int minusMonth = m1.getMonth() - m2.getMonth();if (minusMonth != 0){return minusMonth;}else {return m1.getDay() - m2.getDay();}}}throw new RuntimeException("输入类型异常!");}});treeSet.add(e1);treeSet.add(e2);treeSet.add(e3);treeSet.add(e4);treeSet.add(e5);treeSet.add(e6);Iterator iterator = treeSet.iterator();while (iterator.hasNext()){System.out.println(iterator.next());}}
}

Map接口

  • 双列,用来存储的一对一对(key-value)的对象。
  • Map中的key是无序的,不重复的,使用Set存储所有的key,所以key所在的类要重写hashCode()和equals()。
  • Map中的value是无序的,可重复的,使用Collection存储所有的value,所以value所在的类要重写equals()。
  • 一个键值对key-value构成一个Entry对象,Map中的entry是无序的,不可重复的,使用Set存储所有的entry对象。

Map接口中常用的方法

  • 添加、删除、修改操作:
  1. Object put(Object key,Object value):将指定的key和value添加到当前map对象中,如果key相同,则value覆盖掉原来的value。
  2. putAll(Map map):把map中所有的key-value键值对存放到当前集合对象中。
  3. Object remove(Object key):删除指定key对应的key和value,并返回被删除的value。
  4. void clear():清除当前集合对象中所有的数据。
  • 查询操作:
  1. Object get(Object key):根据指定的key,获取对应的value。
  2. containsKey(Object key):判断当前集合对象是否含有指定的key。
  3. containsValue(Object value):判断当前集合对象是否含有指定的value。
  4. int size():返回集合对象中的key-value个数。
  5. boolean isEmpty():判断当前集合对象是否为空。
  6. boolean equals(Object obj):判断当前集合对象和obj对象是否相等。
  • 元视图操作(用于遍历):
  1. Set keySet():返回所有key构成的Set集合。
  2. Collection Values():返回所有value构成的Collection集合。
  3. Set entrySet():返回所有key-value构成的Set集合。

HashMap

  • HashMap作为Map接口的主要实现类,底层的实现是:数组+链表+红黑树(JDK1.8)。(JDK1.7及之前,底层的实现是数组+链表)
  • new HashMap():底层并没有创建一个长度为16的数组,当HashMap的对象首次调用put()添加数据时,创建长度为16的数组。(不同于JDK.7)
  • 底层的数组默认容量为16,需要扩容则扩容为原来的两倍(*2),并将原有的数据赋值过来,此时数据的存放位置可能跟在原先数组的存放位置不一致(需要重新计算元素在新数组中的位置,再进行存储)。
  • 底层数组是Node[],而非Entry[]。(JDK1.7和1.8的区别之一)
  • 以key-value这种键值对的形式存储数据。
  • 线程不安全,效率高。可存储null的key和value。

HashMap底层的实现:map.put(key1,value1);

首先,调用key1所在类的hashCode()计算key1的哈希值,然后该哈希值经过某种算法计算以后,得到在Node[]数组中的存放位置(即索引位置)。

  • 情况1:如果该位置的数据为空,此时key1-value1添加成功。(以数组的方式存储)

  • 情况2:如果此位置上的数据不为空,意味着此位置上存在一个或多个数据(以链表的方式存在),此时,比较key1和已经存在的一个或多个数据的哈希值,如果key1的哈希值与已存在的任何一个数据都不相同,则key1-value1添加成功。(以链表的方式存储)

  • 情况3:如果key1的哈希值与已存在的某一个数据(key2-value2)的哈希值相同,继续进行比较,调用key1所在类的equals(key2),如果equals()返回false,则key1-value1添加成功。(以链表的方式存储)

  • 情况4:如果equals()返回true,则使用value1覆盖掉value2。

  • 注意:当Node[]数组某一索引位置上的元素以链表存在的形式的数据个数大于8,且此时数组的长度大于64时,此时索引位置上的所有数据改为用红黑树存储。

HashMap的扩容:

  • 扩容涉及到容量,装填因子以及临界值。底层Node[]数组的默认容量为16,默认装填因子为0.75,临界值为容量*装填因子,即默认为12。

  • 当往HashMap集合中添加数据,此时数据以数组的方式存储,而不是以链表的方式存储时,添加数据后,Node[]的长度大于临界值(12)时,Node[]数组进行扩容,*2,容量变成原来的两倍即32,然后把原有的数据赋值,添加到扩容后的数组中,此时临界值重新计算,变成了24。

装填因子的大小对HashMap的影响:

  1. 装填因子的大小决定HashMap数据的密度。

  2. 装填因子越大,密度越大,发生冲突(不同元素,哈希值相同)的几率越大,数组中的链表越容易长,造成查询或插入时比较的次数增多,性能会下降。

  3. 装填因子越小,临界值越小,越容易引发扩容,数据密度也越小,意味着发生冲突的几率越小,数组中的链表也越短,查询和插入时比较的次数也越少,性能会更高,但是会浪费一定的内存空间,而且经常扩容也会影响性能。

  4. 按照其他语言的参考以及研究经验,考虑将装填因子设置为0.7~0.75,此时平均检索长度接近于常数。

HashMap的遍历操作:

public class HashMapTest {@Testpublic void test1(){HashMap hashMap1 = new HashMap();// 往当前集合对象中添加数据hashMap1.put(1001,"旺财");hashMap1.put(1002,"来福");hashMap1.put(1003,"富贵");HashMap hashMap2 = new HashMap();hashMap2.put(1004,"常威");// 将形参集合中的所有key-value添加到当前集合对象中hashMap2.putAll(hashMap1);System.out.println(hashMap2);// 移除指定的key对应的key-value
//        hashMap2.remove(1003);// 遍历集合中的key-value// 方式一:两个迭代器分别获取key和valueSet set = hashMap2.keySet();Collection values = hashMap2.values();Iterator iterator1 = set.iterator();Iterator iterator2 = values.iterator();
//        while (iterator2.hasNext()){//            System.out.println(iterator2.next());
//        }while (iterator1.hasNext() && iterator2.hasNext()){System.out.println(iterator1.next() + "====" + iterator2.next());}System.out.println();// 方式二:通过Entry的getKey()和getValue()获取key和value的值Set set1 = hashMap2.entrySet();Iterator iterator = set1.iterator();while (iterator.hasNext()){Map.Entry entry = (Map.Entry) iterator.next();System.out.println(entry.getKey() + "---->" + entry.getValue());}System.out.println();// 方式三:通过迭代器获取key的值,调用Map接口下的get()方法,根据Key获取value的值。Iterator iterator3 = set.iterator();while (iterator3.hasNext()){Object key = iterator3.next();Object value = hashMap2.get(key);System.out.println(key + "<====>" + value);}}
}

LinkedHaspMap

  • LinkedHashMap是HashMap的子类,底层实现于HashMap一样。
  • LinkedHashMap类里面定义了内部类Entry,该内部类继承了HashMap.Node<k,v>,Entry类里边定义了两个变量before和after,用于记录当前元素的前一个元素和后一个元素,使得LinkedHashMap可以按照元素添加的顺序进行遍历。

TreeMap

  • TreeMap是按照元素的key值进行排序的,因此要求用TreeMap集合存储的对象的key值必须是相同类型。
  • TreeMap可以根据key实现排序遍历,此时考虑key的自然排序或者定制排序。(涉及Comparable和Comparator接口)

Hashtable

  • 古老实现类,JDK1.0就存在,在JDK1.2之后被HashMap代替。

  • 线程安全,效率低。不可以存储null的key和value。

Properties

  • 常用来处理配置文件,key和value都是String类型的。
  • 存取数据时,建议使用setProperty(String key,String value)和getProperty(String key)。

Collections工具类

  • Collections是用于操作Collection(List、Set)和Map的工具类。

Collections中的常用方法:

  • 排序操作:(均为static方法)
  1. reverse(List list):反转list集合中的所有元素。
  2. shuffle(List list):对list集合中的所有元素进行随机排序。
  3. sort(List list):根据元素的自然顺序对指定list集合按升序排序。
  4. sort(List list,Comparator com):根据com定制的排序对指定的list集合进行定制排序。
  5. swap(List list,int i,int j):将list集合中下标为i的元素和下标为j的元素进行交换。
  • 查找、替换:
  1. Object max(Collection coll):根据元素的自然排序,返回给定集合中的最大元素。
  2. Object max(Collection coll,Comparator com):根据com的定制排序,返回给定集合中的最大元素。
  3. Object min(Collection coll):根据元素的自然排序,返回给定集合中的最小元素。
  4. Object min(Collection coll,Comparator com):根据com的定制排序,返回给定集合中的最小元素。
  5. int frequency(Collection coll,Object obj):返回指定对象obj在指定集合coll中出现的次数。
  6. boolean replaceAll(List list,Object oldVal,Object newVal):使用newVal替换集合list中的oldVal。
  7. void copy(List dest,List src):将src中的内容复制到dest中。(注意底层的实现)
  • copy()注意点:
public class CopyTest {@Testpublic void test1(){ArrayList list = new ArrayList();list.add(626);list.add(628);list.add("I'm");list.add("Iron");list.add("Man");//        ArrayList list1 = new ArrayList();// 错误,IndexOutOfBoundsException: Source does not fit in dest,List list1 = Arrays.asList(new Object[list.size()]);Collections.copy(list1,list);System.out.println(list1);}
}


这里的dest相当于list1,src相当于list,如果按照注释掉的代码,一开始,list1.size()是为0的,即dest.size()为0,list中有五个元素,即src.size()为5,即srcSize为5,那么就会抛出异常,所以,要进行复制操作时,可以给空的新集合里面填一个Object[]数组,撑起里面的size,给Object[]数组的长度赋值为被复制的集合的size(),即被复制的集合中有x个元素,就用一个长度为x的Object[]把新数组的size撑起来等于被复制的集合的size。

  • 将指定集合包装成线程同步的集合:(可以解决多线程并发访问集合中的安全问题)
  1. synchronizedList():将指定集合包装成线程同步的List集合。
  2. synchronizedSet():将指定集合包装成线程同步的Set集合。
  3. SynchronizedMap():将指定集合包装成线程同步的Map集合。

即使ArrayList和HashMap是线程不安全的,Vector和Hashtable是线程安全的,但是实际开发中依旧不会去似乎用Vector和Hashtable,而是调用Collections工具类下的指定方法,把ArrayList和HashMap等包装成线程安全的,然后再使用。

集合框架学习笔记:Collection体系和Map体系、Collections工具类相关推荐

  1. java集合框架学习笔记

    思维导图 一.什么是集合 存放在java.util.*.是一个存放对象的容器. 存放的是对象的引用,不是对象本身 长度不固定 只能存放对象 二.collection接口 collection的使用 增 ...

  2. 集合框架(Map容器/Collections工具类)

    >两大主流:collection.map(接口) 底层实现为数组和链表: RationalRose工具:接口与典型实现类: Map为key和value对的形式; >HashMap(线程不安 ...

  3. 集合框架详解之Set、Map接口与实现类

    集合框架 1.Set集合 1.1Set集合概述 Set实现类:HashSet类.TreeSet类 特点:无序.无下标.元素不可重复 方法:全部继承自Collection中的方法 1.11 Set接口的 ...

  4. Spring框架学习笔记04:初探Spring——采用Java配置类管理Bean

    文章目录 一.课程引入 二.采用Java配置类管理Bean (一)打开项目[SpringDemo2021] (二)创建net.hw.spring.lesson04包 (三)创建杀龙任务类 (四)创建勇 ...

  5. Spring框架学习笔记03:初探Spring——利用注解配置类取代Spring配置文件

    文章目录 一.课程引入 二.利用注解配置类取代Spring配置文件 (一)打开项目[SpringDemo2021] (二)创建net.hw.spring.lesson03包 (三)移植上一讲的接口和类 ...

  6. JavaSE中Map框架学习笔记

    前言:最近几天都在生病,退烧之后身体虚弱.头疼.在床上躺了几天,什么事情都干不了.接下来这段时间,要好好加快进度才好. 前面用了三篇文章的篇幅学习了Collection框架的相关内容,而Map框架相对 ...

  7. JavaSE学习总结(十四)Map集合/Map和Collection的区别/HashMap/LinkedHashMap/TreeMap/集合间的嵌套/Hashtable/Collections工具类

    一.Map集合 我们知道,一个学号就能对应一个学生,并且每个学生的学号都不同,学号就像一个键,对应的学生就是该键对应的值.日常生活中经常能见到这种类似学号对应学生的例子.Java 为了我们更加方便地去 ...

  8. SpringMVC框架--学习笔记(上)

    1.SpringMVC入门程序: (1)导入jar包:spring核心jar包.spring-webmvc整合Jar包 (2)配置前端控制器:web.xml文件中 <?xml version=& ...

  9. mybatis框架--学习笔记(下)

    上篇:mybatis框架--学习笔记(上):https://blog.csdn.net/a745233700/article/details/81034021 8.高级映射: (1)一对一查询: ①使 ...

最新文章

  1. opencv python3 找图片色块_Python 图像处理 OpenCV (3):图像属性、图像感兴趣 ROI 区域及通道处理...
  2. 计算机语言wifi,Windows7WIFI热点设置器
  3. *** is required and cannot be removed from the server
  4. c++ 设置类型别名
  5. IIS Tomcat共享80端口
  6. php end array_value,PHP常用处理数组函数
  7. 使用Windows Server 2003搭建一个asp+access网站
  8. Oracle - 查询语句 - 多表关联查询
  9. 终极破产的原因——20年玩儿钱与玩观念的的新经济
  10. C#学习笔记之线程 - 使用线程
  11. [NOI2018]你的名字(68pts)
  12. Java千百问_06数据结构(003)_什么是基本类型包装器
  13. 苹果4放入卡还是显示无服务器,iPhone4S不识别SIM卡 官方出解决方法
  14. python-破译密码
  15. Linux8 搭建缓存DNS服务器
  16. 分布式调用框架RSF-注册中心设计
  17. 华为路由三层交互:单臂路由实验
  18. NPOI导出EXCEL 打印设置分页及打印标题
  19. 极光 · 底层逻辑 · doubleの浮点误差
  20. ORA-06512 问题解决

热门文章

  1. Python学习心得——列表和元组的操作方法
  2. Unity中的Transform Gizmo中的Pivot和Center
  3. 微信小程序前端生成二维码并保存(海报同理)
  4. 论先后,知为先;论轻重,行为重
  5. springboot 签名验证
  6. JavaWeb项目中出现faceted project problem问题是什么原因
  7. wow语音服务器卡蓝条,魔兽世界6.0卡蓝条解决方法 登陆界面卡主解决办法
  8. cups共享linux打印机_利用CUPS为linux安装打印服务并局域网共享
  9. java访问https链接下载图片
  10. 计算机应用基础离线作业2019,天大2019年4月考试《计算机应用基础》在线考核试题【标准答案】...