集合、泛型概述及使用

来源:互联网 发布:网络监察大队图片 编辑:程序博客网 时间:2024/06/03 22:52


1泛型是一种特殊的类型,它把指定类型的工作推迟到客户端代码声明并实例化类或方法的时候进行。

   也被称为参数化类型,可以把类型当作参数一样传递过来,在传递过来之前我不明确,但是在使用的时候我就用明确了。

2泛型的好处

A:提高了程序的安全性

B:将运行期遇到的问题转移到了编译期

  1. C:省去了类型强转的麻烦

 

import java.util.ArrayList;

import java.util.Iterator;

 

/*

 * ArrayList存储字符串并遍历

 *

 * 我们按照正常的写法来写这个程序, 结果确出错了。

 * 为什么呢?

 * 因为我们开始存储的时候,存储了StringInteger两种类型的数据。

 * 而在遍历的时候,我们把它们都当作String类型处理的,做了转换,所以就报错了。

 * 但是呢,它在编译期间却没有告诉我们。

 * 所以,我就觉得这个设计的不好。

 * 回想一下,我们的数组

 * String[] strArray = new String[3];

 * strArray[0] = "hello";

 * strArray[1] = "world";

 * strArray[2] = 10;

 * 集合也模仿着数组的这种做法,在创建对象的时候明确元素的数据类型。这样就不会在有问题了。

 * 而这种技术被称为:泛型。

 *

 * 泛型:是一种把类型明确的工作推迟到创建对象或者调用方法的时候才去明确的特殊的类型。参数化类型,把类型当作参数一样的传递。

 * 格式:

 * <数据类型>

 * 此处的数据类型只能是引用类型。

 * 好处:

 * A:把运行时期的问题提前到了编译期间

 * B:避免了强制类型转换

 * C:优化了程序设计,解决了黄色警告线

 */

public class GenericDemo {public static void main(String[] args) {// 创建ArrayList<String> array = new ArrayList<String>();

 

// 添加元素

array.add("hello");

array.add("world");

array.add("java");

// array.add(new Integer(100));

//array.add(10); // JDK5以后的自动装箱

// 等价于:array.add(Integer.valueOf(10));

 

// 遍历

Iterator<String> it = array.iterator();

while (it.hasNext()) {

// ClassCastException

// String s = (String) it.next();

String s = it.next();

System.out.println(s);

}

 

// 看下面这个代码

// String[] strArray = new String[3];

// strArray[0] = "hello";

// strArray[1] = "world";

// strArray[2] = 10;

}

}

 

 

代码演示

 

import java.util.ArrayList;

import java.util.Iterator;

 

/*

 * 泛型在哪些地方使用呢?

 * API,如果类,接口,抽象类后面跟的有<E>就说要使用泛型。一般来说就是在集合中使用。

 */

public class ArrayListDemo {

public static void main(String[] args) {

// ArrayList存储字符串元素,并遍历。用泛型改进代码

ArrayList<String> array = new ArrayList<String>();

 

array.add("hello");

array.add("world");

array.add("java");

 

Iterator<String> it = array.iterator();

while (it.hasNext()) {

String s = it.next();

System.out.println(s);

}

System.out.println("-----------------");

 

for (int x = 0; x < array.size(); x++) {

String s = array.get(x);

System.out.println(s);

}

}

}

 

 

代码演示二

import java.util.ArrayList;

import java.util.Iterator;

 

/*

 * 需求:存储自定义对象并遍历。

 *

 * A:创建学生类

 * B:创建集合对象

 * C:创建元素对象

 * D:把元素添加到集合

 * E:遍历集合

 */

public class ArrayListDemo2 {

public static void main(String[] args) {

// 创建集合对象

// JDK7的新特性:泛型推断。

// ArrayList<Student> array = new ArrayList<>();

// 但是我不建议这样使用。

ArrayList<Student> array = new ArrayList<Student>();

 

// 创建元素对象

Student s1 = new Student("曹操", 40); // 后知后觉Student s2 = new Student("蒋干", 30); // 不知不觉Student s3 = new Student("诸葛亮", 26);// 先知先觉

 

// 添加元素

array.add(s1);

array.add(s2);

array.add(s3);

 

// 遍历

Iterator<Student> it = array.iterator();

while (it.hasNext()) {

Student s = it.next();

System.out.println(s.getName() + "---" + s.getAge());

}

System.out.println("------------------");

 

for (int x = 0; x < array.size(); x++) {

Student s = array.get(x);

System.out.println(s.getName() + "---" + s.getAge());

}

}

}

 

 

public class Student {

// 姓名

private String name;

// 年龄

private int age;

 

public Student() {

super();

}

 

public Student(String name,int age) {

super();

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;

}

 

}

 

为什么会有泛型呢?

早期的Object类型可以接收任意的对象类型,但是在实际的使用中,会有类型转换的问题。也就存在这隐患,所以Java提供了泛型来解决这个安全问题。

 

泛型应用

泛型类

把泛型定义在类上

格式:public class 类名<泛型类型1,>

注意:泛型类型必须是引用类型

泛型方法

把泛型定义在方法上

格式:public <泛型类型>返回类型 方法名(泛型类型.)

泛型接口

把泛型定义在接口上

格式:public  interface 接口名<泛型类型1>

 

public class ObjectTool {

private Object obj;

 

public Object getObj() {

return obj;

}

 

public void setObj(Object obj) {// Object obj = new Integer(30);

this.obj = obj;

}

}

 

/*

 * 早期的时候,我们使用Object来代表任意的类型。

 * 向上转型是没有任何问题的,但是在向下转型的时候其实隐含了类型转换的问题。

 * 也就是说这样的程序其实并不是安全的。所以JavaJDK5后引入了泛型,提高程序的安全性。

 */

public class ObjectToolDemo {

public static void main(String[] args) {

ObjectTool ot = new ObjectTool();

 

// 正常使用

ot.setObj(new Integer(27));

Integer i = (Integer) ot.getObj();

System.out.println("年龄是:" + i);

 

ot.setObj(new String("林青霞"));

String s = (String) ot.getObj();

System.out.println("姓名是:" + s);

 

System.out.println("---------");

ot.setObj(new Integer(30));

// ClassCastException

String ss = (String) ot.getObj();

System.out.println("姓名是:" + ss);

}

}

 

把泛型定义在类上

/*

 * 泛型类:把泛型定义在类上

 */

public class ObjectTool<T> {

private T obj;

 

public T getObj() {

return obj;

}

 

public void setObj(T obj) {

this.obj = obj;

}

}

 

/*

 * 泛型类的测试

 */

public class ObjectToolDemo {

public static void main(String[] args) {

// ObjectTool ot = new ObjectTool();

//

// ot.setObj(new String("风清扬"));

// String s = (String) ot.getObj();

// System.out.println("姓名是:" + s);

//

// ot.setObj(new Integer(30));

// Integer i = (Integer) ot.getObj();

// System.out.println("年龄是:" + i);

 

// ot.setObj(new String("林青霞"));

// // ClassCastException

// Integer ii = (Integer) ot.getObj();

// System.out.println("姓名是:" + ii);

 

System.out.println("-------------");

 

ObjectTool<String> ot = new ObjectTool<String>();

// ot.setObj(new Integer(27)); //这个时候编译期间就过不去

ot.setObj(new String("林青霞"));

String s = ot.getObj();

System.out.println("姓名是:" + s);

 

ObjectTool<Integer> ot2 = new ObjectTool<Integer>();

// ot2.setObj(new String("风清扬"));//这个时候编译期间就过不去

ot2.setObj(new Integer(27));

Integer i = ot2.getObj();

System.out.println("年龄是:" + i);

}

}

 

 

 泛型方法:把泛型定义在方法上

 

//public class ObjectTool<T> {

//// public void show(String s) {

//// System.out.println(s);

//// }

////

//// public void show(Integer i) {

//// System.out.println(i);

//// }

////

//// public void show(Boolean b) {

//// System.out.println(b);

//// }

//

//public void show(T t) {

//System.out.println(t);

//}

// }

 

/*

 * 泛型方法:把泛型定义在方法上

 */

public class ObjectTool {

public <T> void show(T t) {

System.out.println(t);

}

}

 

public class ObjectToolDemo {

public static void main(String[] args) {

// ObjectTool ot = new ObjectTool();

// ot.show("hello");

// ot.show(100);

// ot.show(true);

 

// ObjectTool<String> ot = new ObjectTool<String>();

// ot.show("hello");

//

// ObjectTool<Integer> ot2 = new ObjectTool<Integer>();

// ot2.show(100);

//

// ObjectTool<Boolean> ot3 = new ObjectTool<Boolean>();

// ot3.show(true);

 

// 如果还听得懂,那就说明泛型类是没有问题的

// 但是呢,谁说了我的方法一定要和类的类型的一致呢?

// 我要是类上没有泛型的话,方法还能不能接收任意类型的参数了呢?

 

// 定义泛型方法后

ObjectTool ot = new ObjectTool();

ot.show("hello");

ot.show(100);

ot.show(true);

}

}

把泛型定义在接口上

/*

 * 泛型接口:把泛型定义在接口上

 */

public interface Inter<T> {

public abstract void show(T t);

}

 

 

//实现类在实现接口的时候

//第一种情况:已经知道该是什么类型的了

 

//public class InterImpl implements Inter<String> {

//

//@Override

//public void show(String t) {

//System.out.println(t);

//}

// }

 

//第二种情况:还不知道是什么类型的

public class InterImpl<T>implements Inter<T> {

 

@Override

public void show(T t) {

System.out.println(t);

}

}

 

public class InterDemo {

public static void main(String[] args) {

// 第一种情况的测试

// Inter<String> i = new InterImpl();

// i.show("hello");

 

// // 第二种情况的测试

Inter<String> i = new InterImpl<String>();

i.show("hello");

 

Inter<Integer> ii = new InterImpl<Integer>();

ii.show(100);

}

}

 

泛型高级(通配符)

泛型通配符<?>

任意类型,如果没有明确,那么就是Object以及任意的Java类了

? extends E

向上限定,E及其子类

? super E

向下限定,E及其父类

 

 

import java.util.ArrayList;

import java.util.Collection;

 

/*

 * 泛型高级(通配符)

 * ?:任意类型,如果没有明确,那么就是Object以及任意的Java类了

 * ? extends E:向下限定,E及其子类

 * ? super E:向上限定,E极其父类

 */

public class GenericDemo {

public static void main(String[] args) {

// 泛型如果明确的写的时候,前后必须一致

Collection<Object> c1 = new ArrayList<Object>();

// Collection<Object> c2 = new ArrayList<Animal>();

// Collection<Object> c3 = new ArrayList<Dog>();

// Collection<Object> c4 = new ArrayList<Cat>();

 

// ?表示任意的类型都是可以的

Collection<?> c5 = new ArrayList<Object>();

Collection<?> c6 = new ArrayList<Animal>();

Collection<?> c7 = new ArrayList<Dog>();

Collection<?> c8 = new ArrayList<Cat>();

 

// ? extends E:向下限定,E及其子类

// Collection<? extends Animal> c9 = new ArrayList<Object>();

Collection<? extends Animal> c10 =new ArrayList<Animal>();

Collection<? extends Animal> c11 =new ArrayList<Dog>();

Collection<? extends Animal> c12 =new ArrayList<Cat>();

 

// ? super E:向上限定,E极其父类

Collection<? super Animal> c13 =new ArrayList<Object>();

Collection<? super Animal> c14 =new ArrayList<Animal>();

// Collection<? super Animal> c15 = new ArrayList<Dog>();

// Collection<? super Animal> c16 = new ArrayList<Cat>();

}

}

class Animal {

}

class Dog extends Animal {

}

class Cat extends Animal {

}

 

 

 

 

 

可变参数概述及使用

可变参数概述

   定义方法的时候不知道该定义多少个参数

格式

   修饰符 返回值类型方法名(数据类型…  变量名){}

注意

  这里的变量其实是一个数组

  如果一个方法有可变参数,并且有多个参数,那么,可变参数肯定是最后一个

/*

 * 可变参数:定义方法的时候不知道该定义多少个参数

 * 格式:

 * 修饰符返回值类型 方法名(数据类型…  变量名){

 *

 * }

 *

 * 注意:

 * 这里的变量其实是一个数组

 * 如果一个方法有可变参数,并且有多个参数,那么,可变参数肯定是最后一个

 */

public class ArgsDemo {

public static void main(String[] args) {

// 2个数据求和

int a = 10;

int b = 20;

int result = sum(a, b);

System.out.println("result:" + result);

 

// 3个数据的求和

int c = 30;

result = sum(a, b, c);

System.out.println("result:" + result);

 

// 4个数据的求和

int d = 30;

result = sum(a, b, c, d);

System.out.println("result:" + result);

 

// 需求:我要写一个求和的功能,到底是几个数据求和呢,我不太清楚,但是我知道在调用的时候我肯定就知道了

// 为了解决这个问题,Java就提供了一个东西:可变参数

result = sum(a, b, c, d, 40);

System.out.println("result:" + result);

 

result = sum(a, b, c, d, 40, 50);

System.out.println("result:" + result);

}

 

public static int sum(int... a) {

// System.out.println(a);

//return 0;

 

int s = 0;

for(int x : a){

s +=x;

}

return s;

}

 

// public static int sum(int a, int b, int c, int d) {

// return a + b + c + d;

// }

//

// public static int sum(int a, int b, int c) {

// return a + b + c;

// }

//

// public static int sum(int a, int b) {

// return a + b;

// }

}

 

 

集合的嵌套遍历

 

 

public class Student {

private String name;

private int age;

 

public Student() {

super();

}

 

public Student(String name,int age) {

super();

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;

}

 

}

 

 

/*

 * 集合的嵌套遍历

 * 需求:

 * 我们班有学生,每一个学生是不是一个对象。所以我们可以使用一个集合表示我们班级的学生。ArrayList<Student>

 * 但是呢,我们旁边是不是还有班级,每个班级是不是也是一个ArrayList<Student>

 * 而我现在有多个ArrayList<Student>。也要用集合存储,怎么办呢?

 * 就是这个样子的:ArrayList<ArrayList<Student>>

 */

public class ArrayListDemo {

public static void main(String[] args) {

// 创建大集合

ArrayList<ArrayList<Student>> bigArrayList = new ArrayList<ArrayList<Student>>();

 

// 创建第一个班级的学生集合

ArrayList<Student> firstArrayList = new ArrayList<Student>();

// 创建学生

Student s1 = new Student("唐僧", 30);

Student s2 = new Student("孙悟空", 29);

Student s3 = new Student("猪八戒", 28);

Student s4 = new Student("沙僧", 27);

Student s5 = new Student("白龙马", 26);

// 学生进班

firstArrayList.add(s1);

firstArrayList.add(s2);

firstArrayList.add(s3);

firstArrayList.add(s4);

firstArrayList.add(s5);

// 把第一个班级存储到学生系统中

bigArrayList.add(firstArrayList);

 

// 创建第二个班级的学生集合

ArrayList<Student> secondArrayList = new ArrayList<Student>();

// 创建学生

Student s11 = new Student("诸葛亮", 30);

Student s22 = new Student("司马懿", 28);

Student s33 = new Student("周瑜", 26);

// 学生进班

secondArrayList.add(s11);

secondArrayList.add(s22);

secondArrayList.add(s33);

// 把第二个班级存储到学生系统中

bigArrayList.add(secondArrayList);

 

// 创建第三个班级的学生集合

ArrayList<Student> thirdArrayList = new ArrayList<Student>();

// 创建学生

Student s111 = new Student("宋江", 40);

Student s222 = new Student("吴用", 35);

Student s333 = new Student("高俅", 30);

Student s444 = new Student("李师师", 22);

// 学生进班

thirdArrayList.add(s111);

thirdArrayList.add(s222);

thirdArrayList.add(s333);

thirdArrayList.add(s444);

// 把第三个班级存储到学生系统中

bigArrayList.add(thirdArrayList);

 

// 遍历集合

for (ArrayList<Student> array : bigArrayList) {

for (Student s : array) {

System.out.println(s.getName() + "---" + s.getAge());

}

}

}

}

 

 

获取101-20之间的随机数,要求不能重复

 用数组实现,但是数组的长度是固定的,长度不好确定。

  所以我们使用集合实现。

 

/*

 * 获取101-20之间的随机数,要求不能重复

 *

 * 用数组实现,但是数组的长度是固定的,长度不好确定。

 * 所以我们使用集合实现。

 *

 * 分析:

 * A:创建产生随机数的对象

 * B:创建一个存储随机数的集合。

 * C:定义一个统计变量。从0开始。

 * D:判断统计遍历是否小于10

 * :先产生一个随机数,判断该随机数在集合中是否存在。

 * 如果不存在:就添加,统计变量++

 * 如果存在:就不搭理它。

 * 否:不搭理它

 * E:遍历集合

 */

public class RandomDemo {

public static void main(String[] args) {

// 创建产生随机数的对象

Random r = new Random();

 

// 创建一个存储随机数的集合。

ArrayList<Integer> array = new ArrayList<Integer>();

 

// 定义一个统计变量。从0开始。

int count = 0;

 

// 判断统计遍历是否小于10

while (count < 10) {

//先产生一个随机数

int number = r.nextInt(20) + 1;

//判断该随机数在集合中是否存在。

if(!array.contains(number)){

//如果不存在:就添加,统计变量++

array.add(number);

count++;

}

}

//遍历集合

for(Integer i : array){

System.out.println(i);

}

}

}

 

 

键盘录入多个数据,以0结束,要求在控制台输出这多个数据中的最大值

 

import java.util.ArrayList;

import java.util.Arrays;

import java.util.Scanner;

 

/*

 * 键盘录入多个数据,以0结束,要求在控制台输出这多个数据中的最大值

 *

 * 分析:

 * A:创建键盘录入数据对象

 * B:键盘录入多个数据,我们不知道多少个,所以用集合存储

 * C:0结束,这个简单,只要键盘录入的数据是0,我就不继续录入数据了

 * D:把集合转成数组

 * E:对数组排序

 * F:获取该数组中的最大索引的值

 */

public class ArrayListDemo {

public static void main(String[] args) {

// 创建键盘录入数据对象

Scanner sc = new Scanner(System.in);

 

// 键盘录入多个数据,我们不知道多少个,所以用集合存储

ArrayList<Integer> array = new ArrayList<Integer>();

 

// 0结束,这个简单,只要键盘录入的数据是0,我就不继续录入数据了

while (true) {

System.out.println("请输入数据:");

int number = sc.nextInt();

if (number != 0) {

array.add(number);

} else {

break;

}

}

 

// 把集合转成数组

// public <T> T[] toArray(T[] a)

Integer[] i = new Integer[array.size()];

// Integer[] ii = array.toArray(i);

array.toArray(i);

// System.out.println(i);

// System.out.println(ii);

 

// 对数组排序

// public static void sort(Object[] a)

Arrays.sort(i);

 

// 获取该数组中的最大索引的值

System.out.println("数组是:" + arrayToString(i) +"最大值是:"

+ i[i.length - 1]);

}

 

public static String arrayToString(Integer[] i) {

StringBuilder sb = new StringBuilder();

 

sb.append("[");

for (int x = 0; x < i.length; x++) {

if (x == i.length - 1) {

sb.append(i[x]);

} else {

sb.append(i[x]).append(", ");

}

}

sb.append("]");

 

return sb.toString();

}

}

 

 

Set接口概述

Set接口概述

一个不包含重复元素的 collection

Set案例

存储字符串并遍历

存储自定义对象并遍历

 

import java.util.HashSet;

import java.util.Set;

 

/*

 * Collection

 * |--List

 * 有序(存储顺序和取出顺序一致),可重复

 * |--Set

 * 无序(存储顺序和取出顺序不一致),唯一

 *

 * HashSet:它不保证set 的迭代顺序;特别是它不保证该顺序恒久不变。

 * 注意:虽然Set集合的元素无序,但是,作为集合来说,它肯定有它自己的存储顺序,

 * 而你的顺序恰好和它的存储顺序一致,这代表不了有序,你可以多存储一些数据,就能看到效果。

 */

public class SetDemo {

public static void main(String[] args) {

// 创建集合对象

Set<String> set = new HashSet<String>();

 

// 创建并添加元素

set.add("hello");

set.add("java");

set.add("world");

set.add("java");

set.add("world");

 

// 增强for

for (String s : set) {

System.out.println(s);

}

}

}

 

 

HashSet类概述

不保证 set 的迭代顺序

特别是它不保证该顺序恒久不变。

 

HashSet如何保证元素唯一性

底层数据结构是哈希表(元素是链表的数组)

哈希表依赖于哈希值存储

添加功能底层依赖两个方法:

   int hashCode()

   boolean equals(Object obj)

 

import java.util.HashSet;

 

/*

 * HashSet:存储字符串并遍历

 * 问题:为什么存储字符串的时候,字符串内容相同的只存储了一个呢?

 * 通过查看add方法的源码,我们知道这个方法底层依赖 两个方法:hashCode()equals()

 * 步骤:

 * 首先比较哈希值

 * 如果相同,继续走,比较地址值或者走equals()

 * 如果不同,就直接添加到集合中

 * 按照方法的步骤来说:

 * 先看hashCode()值是否相同

 * 相同:继续走equals()方法

 * 返回true说明元素重复,就不添加

 * 返回false:说明元素不重复,就添加到集合

 * 不同:就直接把元素添加到集合

 * 如果类没有重写这两个方法,默认使用的Object()。一般来说不同相同。

 * String类重写了hashCode()equals()方法,所以,它就可以把内容相同的字符串去掉。只留下一个。

 */

public class HashSetDemo {

public static void main(String[] args) {

// 创建集合对象

HashSet<String> hs = new HashSet<String>();

 

// 创建并添加元素

hs.add("hello");

hs.add("world");

hs.add("java");

hs.add("world");

 

// 遍历集合

for (String s : hs) {

System.out.println(s);

}

}

}

 

查看源码结构

 

interface Collection {

...

}

 

interface Set extends Collection {

...

}

 

class HashSet implements Set {

private static final Object PRESENT = new Object();

private transient HashMap<E,Object> map;

public HashSet() {

map = new HashMap<>();

}

public boolean add(E e) { //e=hello,world

        return map.put(e, PRESENT)==null;

    }

}

 

class HashMap implements Map {

public V put(K key, V value) { //key=e=hello,world

//看哈希表是否为空,如果空,就开辟空间

        if (table == EMPTY_TABLE) {

            inflateTable(threshold);

        }

        

        //判断对象是否为null

        if (key == null)

            return putForNullKey(value);

        

        int hash = hash(key); //和对象的hashCode()方法相关

        

        //在哈希表中查找hash

        int i = indexFor(hash, table.length);

        for (Entry<K,V> e = table[i]; e != null; e = e.next) {

         //这次的e其实是第一次的world

            Object k;

            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {

                V oldValue = e.value;

                e.value = value;

                e.recordAccess(this);

                return oldValue;

                //走这里其实是没有添加元素

            }

        }

 

        modCount++;

        addEntry(hash, key, value, i); //把元素添加

        return null;

    }

    

    transient int hashSeed = 0;

    

    final int hash(Object k) { //k=key=e=hello,

        int h = hashSeed;

        if (0 != h && k instanceof String) {

            return sun.misc.Hashing.stringHash32((String) k);

        }

 

        h ^= k.hashCode(); //这里调用的是对象的hashCode()方法

 

        // This function ensures that hashCodes that differ only by

        // constant multiples at each bit position have a bounded

        // number of collisions (approximately 8 at default load factor).

        h ^= (h >>> 20) ^ (h >>> 12);

        return h ^ (h >>> 7) ^ (h >>> 4);

    }

}

 

 

hs.add("hello");

hs.add("world");

hs.add("java");

hs.add("world");

 

 

 

public class Student {

private String name;

private int age;

 

public Student() {

super();

}

 

public Student(String name,int age) {

super();

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;

}

 

@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;

Student other = (Student) 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 hashCode() {

// // return 0;

// // 因为成员变量值影响了哈希值,所以我们把成员变量值相加即可

// // return this.name.hashCode() + this.age;

// // 看下面

// // s1:name.hashCode()=40,age=30

// // s2:name.hashCode()=20,age=50

// // 尽可能的区分,我们可以把它们乘以一些整数

// return this.name.hashCode() + this.age * 15;

// }

//

// @Override

// public boolean equals(Object obj) {

// // System.out.println(this + "---" + obj);

// if (this == obj) {

// return true;

// }

//

// if (!(obj instanceof Student)) {

// return false;

// }

//

// Student s = (Student) obj;

// return this.name.equals(s.name) && this.age == s.age;

// }

//

// @Override

// public String toString() {

// return "Student [name=" + name + ", age=" + age + "]";

// }

 

}

import java.util.HashSet;

 

/*

 * 需求:存储自定义对象,并保证元素的唯一性

 * 要求:如果两个对象的成员变量值都相同,则为同一个元素。

 *

 * 目前是不符合我的要求的:因为我们知道HashSet底层依赖的是hashCode()equals()方法。

 * 而这两个方法我们在学生类中没有重写,所以,默认使用的是Object类。

 * 这个时候,他们的哈希值是不会一样的,根本就不会继续判断,执行了添加操作。

 */

public class HashSetDemo2 {

public static void main(String[] args) {

// 创建集合对象

HashSet<Student> hs = new HashSet<Student>();

 

// 创建学生对象

Student s1 = new Student("林青霞", 27);

Student s2 = new Student("柳岩", 22);

Student s3 = new Student("王祖贤", 30);

Student s4 = new Student("林青霞", 27);

Student s5 = new Student("林青霞", 20);

Student s6 = new Student("范冰冰", 22);

 

// 添加元素

hs.add(s1);

hs.add(s2);

hs.add(s3);

hs.add(s4);

hs.add(s5);

hs.add(s6);

 

// 遍历集合

for (Student s : hs) {

System.out.println(s.getName() + "---" + s.getAge());

}

}

}

 

 

 

Set遍历

public class Dog {

private String name;

private int age;

private String color;

private char sex;

 

public Dog() {

super();

}

 

public Dog(String name,int age, String color, char sex) {

super();

this.name = name;

this.age = age;

this.color = color;

this.sex = sex;

}

 

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 String getColor() {

return color;

}

 

public void setColor(String color) {

this.color = color;

}

 

public char getSex() {

return sex;

}

 

public void setSex(char sex) {

this.sex = sex;

}

 

@Override

public int hashCode() {

final int prime = 31;

int result = 1;

result = prime * result + age;

result = prime * result + ((color == null) ? 0 : color.hashCode());

result = prime * result + ((name == null) ? 0 : name.hashCode());

result = prime * result + sex;

return result;

}

 

@Override

public boolean equals(Object obj) {

if (this == obj)

return true;

if (obj == null)

return false;

if (getClass() != obj.getClass())

return false;

Dog other = (Dog) obj;

if (age != other.age)

return false;

if (color == null) {

if (other.color != null)

return false;

} else if (!color.equals(other.color))

return false;

if (name == null) {

if (other.name != null)

return false;

} else if (!name.equals(other.name))

return false;

if (sex != other.sex)

return false;

return true;

}

 

}

 

 

import java.util.HashSet;

 

/*

 * HashSet集合存储自定义对象并遍历。如果对象的成员变量值相同即为同一个对象

 *

 * 注意了:

 * 你使用的是HashSet集合,这个集合的底层是哈希表结构。

 * 而哈希表结构底层依赖:hashCode()equals()方法。

 * 如果你认为对象的成员变量值相同即为同一个对象的话,你就应该重写这两个方法。

 * 如何重写呢?不同担心,自动生成即可。

 */

public class DogDemo {

public static void main(String[] args) {

// 创建集合对象

HashSet<Dog> hs = new HashSet<Dog>();

 

// 创建狗对象

Dog d1 = new Dog("秦桧", 25,"红色",'');

Dog d2 = new Dog("高俅", 22,"黑色",'');

Dog d3 = new Dog("秦桧", 25,"红色",'');

Dog d4 = new Dog("秦桧", 20,"红色",'');

Dog d5 = new Dog("魏忠贤", 28,"白色",'');

Dog d6 = new Dog("李莲英", 23,"黄色",'');

Dog d7 = new Dog("李莲英", 23,"黄色",'');

Dog d8 = new Dog("李莲英", 23,"黄色",'');

 

// 添加元素

hs.add(d1);

hs.add(d2);

hs.add(d3);

hs.add(d4);

hs.add(d5);

hs.add(d6);

hs.add(d7);

hs.add(d8);

 

// 遍历

for (Dog d : hs) {System.out.println(d.getName() + "---" + d.getAge() + "---"+ d.getColor() + "---" + d.getSex());}}} 

0 0