Set接口和泛型

Set接口

Set接口继承于Collection接口,因此它拥有Collection接口的所有方法。它并没有添加新的方法,只是约定不能添加重复的元素。
HashSet HashSet实现了Set接口,不允许重复元素,依赖于元素重写了equals方法。Set是无序的集合,不保存添加元素的顺序,但是对Set进行迭代,每次的顺序都是一致的。

package day20;
import java.util.HashSet;
import java.util.Set;
public class Day2002 {
    
    
public static void main(String[] args) {
    
    
Set<String> set = new HashSet<String>();
set.add("张三");
set.add("李四");
set.add("王五");
set.add("马六");
System.out.println(set.size());//4
//set集合不允许添加重复元素
System.out.println(set.add("张三"));//false
System.out.println(set.size());//4
//对Set进行迭代,每次的顺序都是一致的
for (String str : set) {
    
    
System.out.print(str + " ");
} 
System.out.println();}
} 
package day20;
import java.util.HashSet;
import java.util.Set;
class Animal {
    
    
private String name;
private int age;
public Animal(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;
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;
}
} 
public class Day2003 {
    
    
public static void main(String[] args) {
    
    
Set<Animal> set = new HashSet<Animal>();
set.add(new Animal("小猫", 2));
set.add(new Animal("小狗", 3));
set.add(new Animal("小猫", 2));
System.out.println(set.size());//2
}
}

LinkedHashSet

LinkedHashSet是HashSet的子类,并且其操作和HashSet相同。LinkedHashSet不允许重复的元素,但是保留插入元素的顺序。当对LinkedHashSet进行迭代时,它会按照元素的添加顺序来返回。

package day20;
import java.util.LinkedHashSet;
import java.util.Set;
public class Day2004 {
    
    
public static void main(String[] args) {
    
    
Set<String> set = new LinkedHashSet<String>();
set.add("张三");
set.add("李四");
set.add("王五");
set.add("马六");
System.out.println(set.size());//4
//set集合不允许添加重复元素
System.out.println(set.add("张三"));//false
System.out.println(set.size());//4
//LinkedHashSet保留插入元素的顺序。
//当对其进行迭代时,它会按照元素的添加顺序来返回。
for (String str : set) {
    
    
System.out.print(str + " ");
} S
ystem.out.println();
}
}

TreeSet

TreeSet实现Set接口和SortedSet接口,其操作和HashSet相同。TreeSet不允许重复元素,但是它将元素按照顺序来存储,此顺序不是插入元素的顺序,而是元素的大小顺序。当对TreeSet进行迭代时,它将按照元素的大小顺序来返回。

package day20;
import java.util.Set;
import java.util.TreeSet;
public class Day2005 {
    
    
public static void main(String[] args) {
    
    
Set<Integer> set = new TreeSet<Integer>();
set.add(10);
set.add(20);
set.add(2);
set.add(30);
set.add(5);
// TreeSet将元素按照顺序来存储,此顺序不是插入元素的顺序,而是元素的大小顺序。
for (Integer i : set) {
    
    
System.out.println(i);
} 
System.out.println("***********************");
//添加新的元素会将其放到集合中的合适位置
//TreeSet是在添加元素的时候就排序了
set.add(8);
// TreeSet将元素按照顺序来存储,此顺序不是插入元素的顺序,而是元素的大小顺序。
for (Integer i : set) {
    
    
System.out.println(i);
}
}
}

TreeSet对元素进行排序时需要知道排序规则,有两种方式可以解决: 1,元素实现Comparable接口。 2,创建TreeSet时提供一个比较器。

package day20;
import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;
class TreeSetComparator implements Comparator<Integer>{
    
    
@Override
public int compare(Integer o1, Integer o2) {
    
    
return o2.intValue() - o1.intValue();
}
}
 public class Day2005 {
    
    
public static void main(String[] args) {
    
    
Set<Integer> set = new TreeSet<Integer>(new TreeSetComparator());
set.add(10);
set.add(20);
set.add(2);
set.add(30);
set.add(5);
// TreeSet将元素按照顺序来存储,此顺序不是插入元素的顺序,而是元素的大小顺序。
for (Integer i : set) {
    
    
System.out.println(i);
} 
System.out.println("***********************");
//添加新的元素会将其放到集合中的合适位置
//TreeSet是在添加元素的时候就排序了
set.add(8);
// TreeSet将元素按照顺序来存储,此顺序不是插入元素的顺序,而是元素的大小顺序。
for (Integer i : set) {
    
    
System.out.println(i);
}
}
}

泛型

使用泛型创建的类和方法可以支持不同类型的数据。

package day20;
import java.util.ArrayList;
import java.util.List;
//自定义的有序列表
class MyList1 {
    
    
private List<Object> values = new ArrayList<Object>();public void add(String str) {
    
    
values.add(str);
}
 public void remove(String str) {
    
    
values.remove(str);
}
} 
// 自定义的有序列表
class MyList2 {
    
    
private List<Object> values = new ArrayList<Object>();
public void add(Integer i) {
    
    
values.add(i);
} 
public void remove(Integer i) {
    
    
values.remove(i);
}
} 
//自定义的有序列表
//E是泛型参数
class MyList3<E>{
    
    
private List<Object> values = new ArrayList<Object>();
public void add(E i) {
    
    
values.add(i);
} 
public void remove(E i) {
    
    
values.remove(i);
} 
public E get(int index){
    
    
return (E) values.get(index);
}
}
 public class Day2006 {
    
    
public static void main(String[] args) {
    
    
MyList3 myList31 = new MyList3();
myList31.add("张三");
MyList3 myList32 = new MyList3();
myList32.add(1);
MyList3 myList33 = new MyList3();
myList33.add("abc");
myList33.add("def");
myList33.add("ghi");
Object obj = myList33.get(1);
String str = (String)obj;
System.out.println(str.length());
//泛型的类在使用前需要传递泛型参数
MyList3<String> myList34 = new MyList3<String>();
myList34.add("abc");
String s = myList34.get(0);
System.out.println(s.length());
}
}

在类名后的<>中声明的E代表任意类型,还可以使用M,K,V等等,但是一般都使用T(type),集合中一般使用
E(element),在创建类的对象时,使用具体的类型来代替T。T可以作为类的成员变量的类型,方法的参数和返回
值的类型。

泛型限定

在上面的例子中,T代表此类可以接受任何类型,可以使用泛型限定约束此类能接受的类型

package day20;
import java.util.ArrayList;
import java.util.List;
//泛型限定
//想要MyList4只能存放数值
//E extends Number指示E是number的子类
//表示此泛型类只能使用Number的子类作为泛型参数
class MyList4<E extends Number> {
    
    
private List<Object> list = new ArrayList<Object>();
public void add(E e) {
    
    
list.add(e);
} 
public void remove(E e) {
    
    
list.remove(e);
}
} 
public class Day2007 {
    
    
public static void main(String[] args) {
    
    
//编译错误String并不继承于Number
// MyList4<String> list = new MyList4<String>();
MyList4<Integer> list = new MyList4<Integer>();
}
} 
package day20;
import java.util.ArrayList;
import java.util.List;
class MyList5<E> {
    
    
private List<Object> list = new ArrayList<Object>();
public void add(E e) {
    
    
list.add(e);
}
public void remove(E e) {
    
    
list.remove(e);
} 
//作为方法参数的限定,List<? super E>表示接受的集合中的元素必须是E的超类
public void f(List<? super E> e){
    
    
for (Object object : e) {
    
    
System.out.println(object);
}
}
} 
public class Day2008 {
    
    
public static void main(String[] args) {
    
    
List<String> list1 = new ArrayList<String>();
List<Number> list2 = new ArrayList<Number>();
MyList5<Integer> myList5 = new MyList5<Integer>();
// myList5.f(list1);//编译错误
myList5.f(list2);
}
}

泛型通配符

package day20;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class Day2009 {
    
    
public static void main(String[] args) {
    
    
//list存储Number类型的元素
List<Number> list = new ArrayList<Number>();
//list1存储Integer类型的元素
List<Integer> list1 = new ArrayList<Integer>();
list1.add(1);
list1.add(2);
list1.add(3);
//list2存储Double类型的元素
List<Double> list2 = new ArrayList<Double>();
list2.add(1.0);
list2.add(2.0);
list2.add(3.0);
//list3存储String类型的元素
List<String> list3 = new ArrayList<String>();
list3.add("a");
list3.add("b");
list3.add("c");
//addAll方法将另外一个集合中的元素加入到此集合中
//将list1中的所有元素加入到list中
list.addAll(list1);
//将list2中的所有元素加入到list中
list.addAll(list2);
//将list3中的所有元素加入到list中
// list.addAll(list3);//编译错误
//此方法接受的集合中的元素必须继承于E
//boolean addAll(Collection<? extends E> c);
}
}
``

```java
package day20;
public class Day2010 {
    
    
// 泛型方法
public static <T extends Number> void f1(T t1, T t2) {
    
    
}
 // 泛型方法
public static <E extends Number> E f2(E t1, E t2) {
    
    
return t1;
} 
// 泛型方法
public static <K, V> void f4(K k, V v){
    
    
}
 public static void f3(){
    
    
} 
public static void main(String[] args) {
    
    
f1(1, 1.0);
}
}

猜你喜欢

转载自blog.csdn.net/qq_45092505/article/details/101412583