1.HashSet 集合
java.util.HashSet 是 Set 接口的一个实现类,它所存储的元素是不可重复的,并且元素都是无序的(即存取顺序不一致)。I
HashSet 是根据对象的哈希值来确定元素在集合中的存储位置,因此具有良好的存取和查找性能。
保证元素唯一性的方式依赖于: hashCode与equals方法。
例子:
import java.awt.print.PrinterGraphics;
import java.util.*;
public class Test {
public static void main(String[] args) {
Set<String> a = new HashSet<>();
a.add("aaa");
a.add("bbb");
a.add("aaa");
System.out.println(a);
HashSet<Integer> integers = new HashSet<>();
//Integer 是int的封装类,Integer类型是表示集合里面的内容都是Int类型的
integers.add(10);
integers.add(20);
integers.add(10);
System.out.println(integers);
//集合中的内容不重复
}
}
创建一个student类型的HashSet对象,并输出集合中的内容,此时会输出Hash地址,若想输出实际内容,可以重新定义toString方法。
如果存在重复的元素,则重写equals和hashCode方法
import java.awt.print.PrinterGraphics;
import java.util.*;
public class Test {
public static void main(String[] args) {
Set<Student> students = new HashSet<>();
Student s1 = new Student("刘备",50);
students.add(s1);
students.add(new Student("关羽",48));
System.out.println(students);
}
}
import java.util.Objects;
public class Student {
private String name;
private int age;
//重写toString方法
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
//重写equals(用来比较和判断重复的)和HashCode方法(这个方法是返回哈希地址)
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age && Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
//空构造
public Student() {
}
//满构造
public Student(String name, int age) {
this.name = name;
this.age = age;
}
//get和set方法
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;
}
}
字符串对象.equals(另一个字符串对象):
判断两个对象是否相等,继承于Object类
2.LinkedHashSet集合
HashSet保证元素唯一,可是元素存放进去是没有顺序的,那么我们要保证有序,需要使用它的一个子类LinkedHashSet,它是链表和哈希表组合的一个数据存储结构。 (保证集合元素唯一,谁在前面,谁输出就在前面)
import java.awt.print.PrinterGraphics;
import java.util.*;
public class Test {
public static void main(String[] args) {
LinkedHashSet<String> stringss = new LinkedHashSet<String>();
stringss.add("a");
stringss.add("b");
stringss.add("a");
System.out.println(stringss);
}
}
练习:
判断给定元素在集合中出现的次数
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
public class Test {
public static void main(String[] args) {
ArrayList<String> strings = new ArrayList<>
();
strings.add("a");
strings.add("a");
strings.add("b");
strings.add("b");
strings.add("c");
System.out.println("a:" +
listTest(strings,"a"));
System.out.println("b:" +
listTest(strings,"b"));
System.out.println("c:" +
listTest(strings,"c"));
}
public static int listTest(ArrayList<String> strings, String c) {
//形参列表 形参类型 形参名,形参类型,形参名
//ArrayList<String>代表一个全是String类型的列表类型
int count = 0;
for (String s : strings) {
if(s.equals(c)) {
count++;
}
}
return count;
}
}
三.迭代器
在程序开发中,经常需要遍历集合中的所有元素。针对这种需求, JDK专门提供了一个接口 java.util.lterator。lterator 接口也是Java集合中的一员,但它与Collection 、Map 接口有所不同,
Collection 接口与 Map 接口主要用于存储元素,而 Iterator 主要用于迭代访问(即遍历)Collection 中的元素,因此 lterator 对象也被称为迭代器。
每一个集合都实现了迭代器接口,那么使用迭代器遍历集合的方法为:
。 创建集合对应的迭代器
public lterator iterator():获取集合对应的迭代器,用来遍历集合中的元素的。
创建公式:
Iterator 迭代器名 = 对象列表.iterator();
注意:set是没有序的,所以没有get方法,可以使用foreach和迭代器来访问内部元素
import java.util.*;
public class Test {
public static void main(String[] args) {
Collection<String> strings = new ArrayList<>();
strings.add("a");
strings.add("a");
strings.add("b");
strings.add("c");
System.out.println(strings);
Iterator it = strings.iterator();//创建集合迭代器
Set<Integer> set = new HashSet<>();//创建一个set集合的迭代器
set.add(10);//添加元素
set.add(20);
Iterator it1 = set.iterator();
while(it.hasNext()){//判断是否有下一个元素
System.out.println(it.next());//输出strings集合的元素
System.out.println(it1.next());
}
}
}
四.可变参数
如果我们定义一个方法需要接受多个参数,并且多个参数类型-致,我们可以对其简化成如下格式:
修饰符 返回值类型 方法名(参数类型... 形参名){ }
…. 用在参数上,称之为可变参数
此时调用printMassage可以直接输出数值,及同等类型的数组(把你传的参数(无论是不是数组)变成数组一个一个的输出)
这样就很方便,不需要把所传参数和函数接收参数的类型对应,将参数传到函数后可做出相应操作。
import java.util.*;
public class Test {
public static void main(String[] args) {
int a = 10;
int b = 20;
printMessage(a,b);
int[] arr = {1,2,3};
printMessage(arr);
}
private static void printMessage(int... num) {
for(int t:num)
System.out.println(t);
}
}
泛型
我们在定义集合时,实际上时可以放任意对象的,这是因为集合不身存放的是Object类型,由于任意对象都是Object对象的子类,用以程序不会报错。
泛型的好处:泛型一旦规定了泛型的类型,就只能存规定的类型
import java.io.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class Test {
public static void main(String[] args) throws IOException {
Collection a=new ArrayList();
a.add(10);
a.add("abc");
Iterator iterator = a.iterator();
while(iterator.hasNext())
System.out.println(iterator.next());
}
}
但是当我们在取出每一个对象,并且对每个对象进行相应的操作,这时必须采用类型转换。这是因为尽管Collection能够存储任意对象,但实际上通常Collection只存储同一类型对象。因此在IDK5之后,新增了泛型(Generic)语法,让你在设计API时可以指定类或方法支持泛型,这样我们使用API的时候也变得更为简洁。
自定义泛型的定义和使用
在定义泛型时,可以自己定义泛型的名字
public class MyGenericclass<MVP>{
//没有MVP类型,在这里代表未知的一种数据类型 未来传递什么就是什么类型
private MVP mvp;
public void setMVP(MVP mvp){
this.mvp = mvp;
}
public MVP getMVP(){
return mvp;
}
}