小伙伴们,大家早上好!今天我给大家带来Java集合框架Collection之Set集合讲解,今天主要讲解Set集合接口下的实现类HashSet集合,今天的讲解重要,请大家仔细看噢!
前面我们已经学过了List集合(不熟悉List集合的小伙伴点击:Java进阶-Java学习路线课程第一课:Java集合框架-ArrayList和LinkedList的使用),相信大家对List集合有所了解了吧!List集合是有索引,有序和不唯一,那Set集合有什么特征呢?当然有它的特征,没有索引,无序和唯一。下面我们来一一讲讲,当然,重点会讲一下HashSet去重。
文章目录
- 1、首先,还是让大家看看一个简洁的Java集合框架结构体系图:
- 2、看看这些接口和类有什么特征。
- 3、先给大家演示一下HashSet去重代码,能做到去重吗?代码如下:
- 4、测试代码:
- 5、输出结果:
- 6、从上面的打印中可以看出:
- 7、输出结果:
- 8、很显然,java系统类在向Set或HashSet集合里增加元素时,已经完美的去重了。那我们就看看String类里重写了哪些方法,我们来借鉴一下!惊奇的发现了String重写Object超类中的两个方法:一个是equals方法(前面介绍过:[Java入门-Java学习路线扩展课程:equals的使用](https://blog.csdn.net/atgfg/article/details/102576039)),另一个是hashCode方法。源码如下:
- 9、原来如此,String类用属性value值作为底层数据来计算hashCode的,即相同的value就一定会有相同的哈希值。如果value值相同,那么调用equals方法比较也是相等的;反过来不一定成立。它不保证相同的哈希值一定就是相同的对象。
- 10、在Java中,String类有个别对象的属性值不同,但是哈希值相同,比如字符串"gdejicbegh"与字符串"hgebcijedg"具有相同的哈希值-801038016。代码如下:
- 11、输出结果:
- 12、结论如下:
- 13、小伙伴们是不是有种豁然开朗的感觉?我们来改造一下News.java类,改造代码如下:
- 14、测试代码:
- 15、输出结果:
- 17、HashSet去重原理:
- 小伙伴们,本章已经结束,你们都懂了吗?我花了四个小时的时间编写,记得关注、点赞、分享和关注微信公众号(javaforum)噢!有疑问或好的建议请与我联系噢!持续更新!敬请关注!
1、首先,还是让大家看看一个简洁的Java集合框架结构体系图:
2、看看这些接口和类有什么特征。
- Collection(接口)
特征(单列集合): 不唯一,无序
- List(子接口)
特征(单列集合): 不唯一,有序
- Set(子接口)
特征(单列集合): 唯一,无序
- Map(接口)
特征(双列集合): 键值对
key --->value map.put("userName",uName);
key是拿的Set的特性,而value是拿的Collection的特性。
- HashSet
特征:底层由哈希表(实际上是一个 HashMap
实例)支持。它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用 null 元素。无索引,唯一,无序。最大的优势就是去重。
3、先给大家演示一下HashSet去重代码,能做到去重吗?代码如下:
News.java 实例类
package com.javaxyz.entity;
/**
* @ClassName:News.java
* @Description:新闻实例类
* @Author:DongGaoYun
* @AuthorEnglishName:Andy
* @URL:www.javaxyz.com 或 www.gyun.org
* @Email:DongGaoYun@qq.com
* @QQ:1050968899
* @WeiXin:QingYunJiao
* @WeiXinGongZhongHao: JavaForum
* @Date:2019-10-22 下午2:23:38
* @Version:1.0 完成以下基本代码: 1.属性 2.get和set方法 3.构造方法 4.toString
* 说明
1.这个新闻实例类没有重写equals和hashCode方法
2.没有用泛型,后面章节会介绍
*/
public class News {
//属性
private int id;
private String title;//标题
private String author;//作者
/**
* @return the id
*/
public int getId() {
return id;
}
/**
* @param id
* the id to set
*/
public void setId(int id) {
this.id = id;
}
/**
* @return the title
*/
public String getTitle() {
return title;
}
/**
* @param title
* the title to set
*/
public void setTitle(String title) {
this.title = title;
}
/**
* @return the author
*/
public String getAuthor() {
return author;
}
/**
* @param author
* the author to set
*/
public void setAuthor(String author) {
this.author = author;
}
// toString
@Override
public String toString() {
return "News [id=" + id + "," + " title=" + title + "," + " author="
+ author + "]\n";
}
/**
* 无参构造方法
*/
public News() {
}
/**
* 有参构造方法
* @param id
* @param title
* @param author
*/
public News(int id, String title, String author) {
super();
this.id = id;
this.title = title;
this.author = author;
}
}
4、测试代码:
package com.javaxyz.test;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.junit.Test;
import com.javaxyz.equals.News;
/**
* @ClassName:HashSetDemo.java
* @Description:Set的运用
* @Author:DongGaoYun
* @AuthorEnglishName:Andy
* @URL:www.javaxyz.com 或 www.gyun.org
* @Email:DongGaoYun@qq.com
* @QQ:1050968899
* @WeiXin:QingYunJiao
* @WeiXinGongZhongHao: JavaForum
* @Date:2019-10-25
* @Version:1.0 HashSet 优势: 去重 特有功能:
*
*/
public class HashSetDemo1 {
// 需求:
// 增加新闻元素
// 获取新闻总数
// 操作HashSet容器,移除元素
// 判断是否包含此元素
// 打印输出四种方式
//忽略警告
@SuppressWarnings("all")
// public static void main(String[] args) {
@Test
public void testSet() {
// 创建对象
// 创建多态的形式,要注意的点:只能调用父类与子类重写的方法,子类特有方法无法调用
Set list = new HashSet();// 多态的形式。//1.父子关系 2.重写方法 3.父类的引用指向子类对象
News news1 = new News(1, "张卓1", "green1");
News news2 = new News(2, "张卓2", "green2");
News news11 = new News(2, "张卓2", "green2");
News news3 = new News(3, "张卓3", "green3");
News news4 = new News(4, "张卓4", "green4");
News news5 = new News(5, "张卓5", "green5");
News news6 = new News(6, "张卓6", "green6");
News news7 = new News(7, "张卓7", "green7");
News news8 = new News(8, "张卓8", "green8");
// 插入数据
list.add(news1);
list.add(news2);
list.add(news3);
// 注意set是无序的,没有索引,所以报错
// list.add(1,news4);
// 插入数据
list.add(news6);
list.add(news11);
// 总条数
System.out.println(list.size());
// 操作HashSet容器,移除元素
/*
* list.remove(0); list.remove(news1);
*/
// 判断是否包含此元素
System.out.println(list.contains(news7));
// list
System.out.println("-------第一种打印输出方法---start----");
System.out.print(list);
System.out.println("-------第一种打印输出方法---end----");
System.out.println();
//System.out.println("-------第二种打印输出方法-普通for--start----");
// 普通for不能用
/*
* for (int i = 0; i < list.size(); i++) { News newss = (News)
* list.get(i); System.out.println("News [id=" + newss.getId() + "," +
* " title=" + newss.getTitle() + "," + " author=" + newss.getAuthor() +
* "]"); }
*/
//System.out.println("-------第二种打印输出方法---end----");
System.out.println();
System.out.println("-------第二种打印输出方法-增强for--start----");
for (Object object : list) {
News newss = (News) object;
System.out.println("News [id=" + newss.getId() + "," + " title="
+ newss.getTitle() + "," + " author=" + newss.getAuthor()
+ "]");
}
System.out.println("-------第二种打印输出方法---end----");
System.out.println();
System.out.println("-------第三种打印输出方法-转换成数组--start----");
/**
* toArray Object[] toArray() 返回包含此 collection 中所有元素的数组。如果 collection
* 对其迭代器返回的元素顺序做出了某些保证,那么此方法必须以相同的顺序返回这些元素。 返回的数组将是“安全的”,因为此 collection
* 并不维护对返回数组的任何引用。(换句话说,即使 collection
* 受到数组的支持,此方法也必须分配一个新的数组)。因此,调用者可以随意修改返回的数组。
*
* 此方法充当了基于数组的 API 与基于 collection 的 API 之间的桥梁。
*
* 返回: 包含此 collection 中所有元素的数组
*/
Object[] obj = list.toArray();
for (Object object : obj) {
News newss = (News) object;
System.out.println("News [id=" + newss.getId() + "," + " title="
+ newss.getTitle() + "," + " author=" + newss.getAuthor()
+ "]");
}
System.out.println("-------第三种打印输出方法---end----");
System.out.println();
System.out.println("-------第四种打印输出方法-迭代方式--start----");
/**
* iterator Iterator<E> iterator()
*
* boolean hasNext() 如果仍有元素可以迭代,则返回 true。
*
* E next() 返回迭代的下一个元素。
*
* void remove() 从迭代器指向的 collection 中移除迭代器返回的最后一个元素(可选操作)。
*/
Iterator it = list.iterator();
while (it.hasNext()) {
News newss = (News) it.next();
System.out.println("News [id=" + newss.getId() + "," + " title="
+ newss.getTitle() + "," + " author=" + newss.getAuthor()
+ "]");
}
System.out.println("-------第四种打印输出方法---end----");
}
}
5、输出结果:
5
false
-------第一种打印输出方法---start----
[News [id=1, title=张卓1, author=green1]
, News [id=2, title=张卓2, author=green2]
, News [id=3, title=张卓3, author=green3]
, News [id=2, title=张卓2, author=green2]
, News [id=6, title=张卓6, author=green6]
]-------第一种打印输出方法---end----
-------第二种打印输出方法-增强for--start----
News [id=1, title=张卓1, author=green1]
News [id=2, title=张卓2, author=green2]
News [id=3, title=张卓3, author=green3]
News [id=2, title=张卓2, author=green2]
News [id=6, title=张卓6, author=green6]
-------第二种打印输出方法---end----
-------第三种打印输出方法-转换成数组--start----
News [id=1, title=张卓1, author=green1]
News [id=2, title=张卓2, author=green2]
News [id=3, title=张卓3, author=green3]
News [id=2, title=张卓2, author=green2]
News [id=6, title=张卓6, author=green6]
-------第三种打印输出方法---end----
-------第四种打印输出方法-迭代方式--start----
News [id=1, title=张卓1, author=green1]
News [id=2, title=张卓2, author=green2]
News [id=3, title=张卓3, author=green3]
News [id=2, title=张卓2, author=green2]
News [id=6, title=张卓6, author=green6]
-------第四种打印输出方法---end----
6、从上面的打印中可以看出:
- Set的输出是无序的;
- Set虽然说具有去重的功能,但是自定义对象增加到Set集合或HashSet集合中,还是有重复的对象,怎么办呢?有什么玄机呢?为什么没有去重呢?我们还是看看java的系统类String,我们在String类中把相同的对象增加进去会去重吗?我们来试试。具体代码如下:
public class HashSetDemo2_String {
// 需求:
// 增加新闻元素
// 获取新闻总数
// String类,如果在HashSet容器增加元素,如果增加的元素是相同的,就会去重。
@SuppressWarnings("all")
// public static void main(String[] args) {
@Test
public void testSet() {
// 创建对象
// 创建多态的形式,要注意的点:只能调用父类与子类重写的方法,子类特有方法无法调用
// Set list=new HashSet();//多态的形式。//1.父子关系 2.重写方法 3.父类的引用指向子类对象
HashSet list = new HashSet();
String s1 = new String("abc");
String s2 = new String("abc");
String s3 = new String("abc");
// 增加元素
list.add(s1);
// 注意:当向set集合中存储相同元素时,add(obj)方法返回的是false.
list.add(s2);
list.add(s3);
// 获取元素总数
System.out.println(list.size());
System.out.println();
//打印输出
System.out.println(list);
}
}
7、输出结果:
1
[abc]
8、很显然,java系统类在向Set或HashSet集合里增加元素时,已经完美的去重了。那我们就看看String类里重写了哪些方法,我们来借鉴一下!惊奇的发现了String重写Object超类中的两个方法:一个是equals方法(前面介绍过:Java入门-Java学习路线扩展课程:equals的使用),另一个是hashCode方法。源码如下:
- 重写equals方法
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String) anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
- 重写hashCode方法
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}
9、原来如此,String类用属性value值作为底层数据来计算hashCode的,即相同的value就一定会有相同的哈希值。如果value值相同,那么调用equals方法比较也是相等的;反过来不一定成立。它不保证相同的哈希值一定就是相同的对象。
10、在Java中,String类有个别对象的属性值不同,但是哈希值相同,比如字符串"gdejicbegh"与字符串"hgebcijedg"具有相同的哈希值-801038016。代码如下:
HashSet list = new HashSet();
String s1 = new String("gdejicbegh");
String s2 = new String("hgebcijedg");
System.out.println(s1.hashCode()==s2.hashCode());
System.out.println(s1.hashCode());
System.out.println(s2.hashCode());
11、输出结果:
true
-801038016
-801038016
12、结论如下:
- 如果equals比较后相等,则hashCode一定会相等。 更多免费资料请加微信公众号:javaforum
- 如果hashCode的哈希值相等,equals就不一定相等,注意:它不保证相同的哈希值一定就是相同的对象。
13、小伙伴们是不是有种豁然开朗的感觉?我们来改造一下News.java类,改造代码如下:
package com.javaxyz.equals;
/**
* @ClassName:News.java
* @Description:描述信息
* @Author:DongGaoYun
* @AuthorEnglishName:Andy
* @URL:www.javaxyz.com 或 www.gyun.org
* @Email:DongGaoYun@qq.com
* @QQ:1050968899
* @WeiXin:QingYunJiao
* @WeiXinGongZhongHao: JavaForum
* @Date:2019-10-22 下午2:23:38
* @Version:1.0
* 完成以下基本代码: 1.属性 2.get和set方法 3.构造方法 4.toString
* 重写Object的两个方法
* 1.hashCode方法
* 2.equals方法
* Set集合即可去重。
*
*/
public class News {
// 属性
private int id;
private String title;// 标题
private String author;// 作者
/**
* @return the id
*/
public int getId() {
return id;
}
/**
* @param id
* the id to set
*/
public void setId(int id) {
this.id = id;
}
/**
* @return the title
*/
public String getTitle() {
return title;
}
/**
* @param title
* the title to set
*/
public void setTitle(String title) {
this.title = title;
}
/**
* @return the author
*/
public String getAuthor() {
return author;
}
/**
* @param author
* the author to set
*/
public void setAuthor(String author) {
this.author = author;
}
// toString
@Override
public String toString() {
return "News [id=" + id + "," + " title=" + title + "," + " author="
+ author + "]\n";
}
/**
* 无参构造方法
*/
public News() {
}
/**
* 有参构造方法
*
* @param id
* @param title
* @param author
*/
public News(int id, String title, String author) {
super();
this.id = id;
this.title = title;
this.author = author;
}
/*
* 为什么把prime变量值初始化为31,有以下几个原因:更多免费资料请加微信公众号:javaforum
* 1.31这个数字不大也不太小
* 2.31是一个奇数,也是一个质数,即只能被1和本身整除的数。
* 3.如果选择偶数,乘2相当于移位运算可能导致溢出,数据会丢失
* 4.31有个很好的特性,就是用移位和减法来代替乘法,可以得到更好的性能:31*i==(i<<5)-i。现在的JVM可以自动完成这种优化。 *
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((author == null) ? 0 : author.hashCode());
result = prime * result + id;
result = prime * result + ((title == null) ? 0 : title.hashCode());
System.out.println("执行的hashCode是:"+result);
return result;
}
/*
* 在我的博文中已经讲过: Java入门-Java学习路线扩展课程:equals的使用 更多免费资料请加微信公众号:javaforum
*/
@Override
public boolean equals(Object obj) {
//提升效率 判断传入的对象与本对象是否是同一个对象
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())//比较两个对象的字节码文件是否是同一个字节码
return false;
News other = (News) obj;//向下转型
if (author == null) {
if (other.author != null)
return false;
} else if (!author.equals(other.author))
return false;
if (id != other.id)
return false;
if (title == null) {
if (other.title != null)
return false;
} else if (!title.equals(other.title))
return false;
return true;
}
}
14、测试代码:
package com.javaxyz.test;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.junit.Test;
import com.javaxyz.equals.News;
/**
* @ClassName:HashSetDemo.java
* @Description:Set的运用
* @Author:DongGaoYun
* @AuthorEnglishName:Andy
* @URL:www.javaxyz.com 或 www.gyun.org
* @Email:DongGaoYun@qq.com
* @QQ:1050968899
* @WeiXin:QingYunJiao
* @WeiXinGongZhongHao: JavaForum
* @Date:2019-10-25
* @Version:1.0 HashSet 优势: 去重 特有功能:
*
*/
public class HashSetDemo1 {
// 需求:
// 增加新闻元素
// 获取新闻总数
// 操作HashSet容器,移除元素
// 判断是否包含此元素
// 打印输出四种方式
// String类,如果在HashSet容器增加元素,如果增加的元素是相同的,就会去重。
@SuppressWarnings("all")
// public static void main(String[] args) {
@Test
public void testSet() {
// 创建对象
// 创建多态的形式,要注意的点:只能调用父类与子类重写的方法,子类特有方法无法调用
Set list = new HashSet();// 多态的形式。//1.父子关系 2.重写方法 3.父类的引用指向子类对象
String s1 = new String("gdejicbegh");
String s2 = new String("hgebcijedg");
System.out.println(s1.hashCode()==s2.hashCode());
System.out.println(s1.hashCode());
System.out.println(s2.hashCode());
// list.add(s1);
// list.add(s2);
//System.out.println(list.size());
News news1 = new News(1, "张卓1", "green1");
News news2 = new News(2, "张卓2", "green2");
News news11 = new News(2, "张卓2", "green2");
News news3 = new News(3, "张卓3", "green3");
News news4 = new News(4, "张卓4", "green4");
News news5 = new News(5, "张卓5", "green5");
News news6 = new News(6, "张卓6", "green6");
News news7 = new News(7, "张卓7", "green7");
News news8 = new News(8, "张卓8", "green8");
// 插入数据
list.add(news1);
list.add(news2);
list.add(news3);
// 注意set是无序的,没有索引,所以报错 更多免费资料请加微信公众号:javaforum
// list.add(1,news4);
// 插入数据
list.add(news6);
//注意:自定义对象重写equals和hashCode方法后,如果是重复元素,这时就会返回false
System.out.println(list.add(news11));
// 总条数
System.out.println(list.size());
// 操作HashSet容器,移除元素
/*
* list.remove(0); list.remove(news1);
*/
// 判断是否包含此元素
System.out.println(list.contains(news7));
// list
System.out.println("-------第一种打印输出方法---start----");
System.out.print(list);
System.out.println("-------第一种打印输出方法---end----");
System.out.println();
//System.out.println("-------第二种打印输出方法-普通for--start----");
// 普通for不能用
/*
* for (int i = 0; i < list.size(); i++) { News newss = (News)
* list.get(i); System.out.println("News [id=" + newss.getId() + "," +
* " title=" + newss.getTitle() + "," + " author=" + newss.getAuthor() +
* "]"); }
*/
//System.out.println("-------第二种打印输出方法---end----");
System.out.println();
System.out.println("-------第二种打印输出方法-增强for--start----");
for (Object object : list) {
News newss = (News) object;
System.out.println("News [id=" + newss.getId() + "," + " title="
+ newss.getTitle() + "," + " author=" + newss.getAuthor()
+ "]");
}
System.out.println("-------第二种打印输出方法---end----");
System.out.println();
System.out.println("-------第三种打印输出方法-转换成数组--start----");
/**
* toArray Object[] toArray() 返回包含此 collection 中所有元素的数组。如果 collection
* 对其迭代器返回的元素顺序做出了某些保证,那么此方法必须以相同的顺序返回这些元素。 返回的数组将是“安全的”,因为此 collection
* 并不维护对返回数组的任何引用。(换句话说,即使 collection
* 受到数组的支持,此方法也必须分配一个新的数组)。因此,调用者可以随意修改返回的数组。
*
* 此方法充当了基于数组的 API 与基于 collection 的 API 之间的桥梁。
*
* 返回: 包含此 collection 中所有元素的数组 更多免费资料请加微信公众号:javaforum
*/
Object[] obj = list.toArray();
for (Object object : obj) {
News newss = (News) object;
System.out.println("News [id=" + newss.getId() + "," + " title="
+ newss.getTitle() + "," + " author=" + newss.getAuthor()
+ "]");
}
System.out.println("-------第三种打印输出方法---end----");
System.out.println();
System.out.println("-------第四种打印输出方法-迭代方式--start----");
/**
* iterator Iterator<E> iterator()
*
* boolean hasNext() 如果仍有元素可以迭代,则返回 true。
*
* E next() 返回迭代的下一个元素。 更多免费资料请加微信公众号:javaforum
*
* void remove() 从迭代器指向的 collection 中移除迭代器返回的最后一个元素(可选操作)。
*/
Iterator it = list.iterator();
while (it.hasNext()) {
News newss = (News) it.next();
System.out.println("News [id=" + newss.getId() + "," + " title="
+ newss.getTitle() + "," + " author=" + newss.getAuthor()
+ "]");
}
System.out.println("-------第四种打印输出方法---end----");
}
}
15、输出结果:
true
-801038016
-801038016
false
4
false
-------第一种打印输出方法---start----
[News [id=1, title=张卓1, author=green1]
, News [id=2, title=张卓2, author=green2]
, News [id=6, title=张卓6, author=green6]
, News [id=3, title=张卓3, author=green3]
]-------第一种打印输出方法---end----
-------第二种打印输出方法-增强for--start----
News [id=1, title=张卓1, author=green1]
News [id=2, title=张卓2, author=green2]
News [id=6, title=张卓6, author=green6]
News [id=3, title=张卓3, author=green3]
-------第二种打印输出方法---end----
-------第三种打印输出方法-转换成数组--start----
News [id=1, title=张卓1, author=green1]
News [id=2, title=张卓2, author=green2]
News [id=6, title=张卓6, author=green6]
News [id=3, title=张卓3, author=green3]
-------第三种打印输出方法---end----
-------第四种打印输出方法-迭代方式--start----
News [id=1, title=张卓1, author=green1]
News [id=2, title=张卓2, author=green2]
News [id=6, title=张卓6, author=green6]
News [id=3, title=张卓3, author=green3]
-------第四种打印输出方法---end----
16、由此可见,要想将自定义类的对象存入HashSet集合里去重,需要注意以下三点:
- 自定义类中必须同时重写equals()和hashCode()方法
- hashCode(): 属性值相同的对象返回值必须相同, 属性值不同的返回值尽量不同(提高效率)
- equals(): 属性值相同返回true, 属性值不同返回false,返回false的时候存储
17、HashSet去重原理:
17.1、使用HashSet集合调用add()方法存储对象之前,应该注意尽量使重写的hashCode()方法返回的值不同,减少调用equals方法,提升性能;在调用add方法时,系统会先调用对象的hashCode()方法得到一个哈希值, 然后在HashSet集合中比较是否有哈希值相同的对象
- 如果没有哈希值相同的对象就会直接存入HashSet集合
- 如果有哈希值相同的对象, 就和哈希值相同的对象逐个调用equals()方法进行比较,结果为false就直接存入, 为true则不存
小伙伴们,本章已经结束,你们都懂了吗?我花了四个小时的时间编写,记得关注、点赞、分享和关注微信公众号(javaforum)噢!有疑问或好的建议请与我联系噢!持续更新!敬请关注!
- Java入门-Java学习路线课程第一课:初识JAVA
- Java入门-Java学习路线课程第二课:变量与数据类型
- Java入门-Java学习路线课程第三课:选择结构
- Java入门-Java学习路线课程第四课:循环结构
- Java入门-Java学习路线课程第五课:一维数组
- Java入门-Java学习路线课程第六课:二维数组
- Java入门-Java学习路线课程第七课:类和对象
- Java入门-Java学习路线课程第八课:方法和方法重载
- Java入门-Java学习路线扩展课程:equals的使用
- Java入门-Java学习路线课程面试篇:取商 / 和取余(模) % 符号的使用
- Java进阶-Java学习路线课程第一课:Java集合框架-ArrayList和LinkedList的使用
- Spring框架-Java学习路线课程第一课:Spring核心
- Spring框架-Java学习路线课程:Spring的扩展配置
- Springboot框架-Java学习路线课程:Springboot框架的搭建之maven的配置
- java学习:在给学生演示用Myeclipse10.7.1工具生成War时,意外报错:SECURITY: INTEGRITY CHECK ERROR
- 使用jquery发送Ajax请求的几种异步刷新方式
- idea Springboot启动时内嵌tomcat报错- An incompatible version [1.1.33] of the APR based Apache Tomcat Native
- 一个简单的SSM框架Demo(登录(包含拦截器)和注销