java中的接口是类吗
192
2023-04-08
Java复习之集合框架总结
俗话说:温故而知新。想想学过的知识,就算是以前学得很不错,久不用了,就会忘记,所以温习一下以前学习的知识我认为是非常有必要的。而本篇文件温习的是 java基础中的集合框架。
为什么会有集合框架?
平时我们用数组存储一些基本的数据类型,或者是引用数据类型,但是数组的长度是固定的,当添加的元素超过了数组的长度时,需要对数组进行重新的定义,这样就会显得写程序太麻烦,所以Java内部为了我们方便,就提供了集合类,能存储任意对象,长度是可以改变的,随着元素的增加而增加,随着元素的减少而减少。
数组可以存储基本数据类型,也可以存储引用数据类型,基本数据类型存储的是值,引用数据类型存储的是地址,而集合只能存储引用数据类型(也就是对象),其实集合中也可以存储基本数据类型,但是在存储的时候会自动装箱变成对象。
有了集合不意味着我们要抛弃数组,如果需要存储的元素个数是固定的,我们可以使用数组,而当存储的元素不固定,我们使用集合。
集合的种类
集合分为单列集合和双列集合。单列集合的根接口为Collection,双列结合的根接口为Map,两种集合都有基于哈希算法的集合类(HashMap和HashSet),现在我们可能会有疑问,到底是双列集合基于单列集合还是单列集合基于双列集合呢,下面我们来看往集合HashMap和HashSet添加元素的源码:
/*
*HashMap的put 方法
*/
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
Node
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
else {
Node
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
else if (p instanceof TreeNode)
e = ((TreeNode
else {
for (int binCount = 0; ; ++binCount) {
if ((e = p.next) == null) {
p.next = newNode(hash, key, value, null);
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
break;
}
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
}
}
if (e != null) { // existing mapping for key
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e);
return oldValue;
}
}
++modCount;
if (++size > threshold)
resize();
afterNodeInsertion(evict);
return null;
}
/*
* HashSet 的add 方法
*/
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
// PRESENT是一个Object 对象
private static final Object PRESENT = new Object();
由上源码,我们可以看出,双列集合的put方法源码中并没有出现add方法,而单列集合的add源码只能怪出现了put;我们可以知道单列集合是基于双列集合实现的。其实道理很简单,单列集合每次添加元素,只要添加key就可以,而key也是双列集合元素的唯一标识,而其值value则由一个Object对象代替并且隐藏,每次加入,输出元素都是隐藏单列结合的这个值, 底层基于双列集合,隐藏一列是很好实现的,而如果是单列集合要变成双列集合估计就会有很大的难度,就好比魔术师变魔术,魔术师变东西前肯定事先准备好要变的东西,只是将其隐藏,但是如果魔术师变魔术是真的从无到有,那我估计他就是神仙了,想要什么就变出来什么便是。
单列集合
首先我们看单列结合的继承图,单列集合的根接口是Collection,而List的实现类为ArrayList、LinkedList、Vector,Set接口的实现类是HashSet和TreeSet。
其次我们来看看各个集合的功能
List集合的特有功能概述
* void add(int index,E element) //集合中添加元素
* E remove(int index) //删除集合中index位置上的元素
* E get(int index) //获取集合中index位置上的元素
* E set(int index,E element) 将index位置上的元素替换成 element
Vector类特有功能
* public void addElement(E obj) 添加元素
* public E elementAt(int index) //获取元素
* public Enumeration elements() //获取元素的枚举(迭代遍历的时候用到)
LinkedList类特有功能
* public void addFirst(E e)及addLast(E e) //集合头添加元素或者集合尾添加元素
* public E getFirst()及getLgFxivXast() //获取头元素 获取尾元素
* public E removeFirst()及public E removeLast() //删除头元素删除尾元素
* public E get(int index);//获取index元素
根据上述LinkedList的功能,我们可以模拟栈获取队列的数据结构,栈是先进后出,队列为先进先出。
/**
* 模拟的栈对象
* @author 毛麒添
* 底层还是使用LinkedList实现
* 如果实现队列只需要将出栈变为 removeFirst
*/
public class Stack {
private LinkedList linklist=new LinkedList();
/**
* 进栈的方法
* @param obj
*/
public void in(Object obj){
linklist.addLast(obj);
}
/**
* 出栈
*/
public Object out(){
return linklist.removeLast();
}
/**
* 栈是否为空
* @return
*/
public boolean isEmpty(){
return linklist.isEmpty();
}
}
//集合的三种迭代(遍历集合)删除
ArrayList
list.add("a");
list.add("b");
list.add("c");
list.add("world");
//1,普通for循环删除元素
for(int i=0;i if("b".equals(list.get(i))){ list.remove(i--);// i-- 当集合中有重复元素的时候保证要删除的重复元素被删除 } } //2.使用迭代器遍历集合 Iterator while(it.hasNext){ if("b".equals(it.next())){ it.remove();//这里必须使用迭代器的删除方法,而不能使用集合的删除方法,否则会出现并发修改异常(ConcurrentModificationException) } } //使用增强for循环来进行删除 for (String str:list){ if("b".equals(str)){ list.remove("b");//增强for循环底层依赖的是迭代器,而这里删除使用的依旧是集合的删除方法,同理肯定是会出现并发修改异常(ConcurrentModificationException),所以增强for循环一直能用来遍历集合,不能对集合的元素进行删除。 } } 接下里我们看Set集合,我们知道Set 集合存储无序,无索引,不可以存储重复的对象;我们使用Set集合都是需要去掉重复元素的, 如果在存储的时候逐个equals()比较, 效率较低,哈希算法提高了去重复的效率, 降低了使用equals()方法的次数,其中HashSet底层基于哈希算法,当HashSet调用add方法存储对象,先调用对象的hashCode()方法得到一个哈希值, 然后在集合中查找是否有哈希值相同的对象,如果没有哈希值相同的对象就直接存入集合,如果有哈希值相同的对象, 就和哈希值相同的对象逐个进行equals()比较,比较结果为false就存入, true则不存。下面给出HashSet存储自定义对象的一个例子,自定义对象需要重写hashCode()和equals()方法。 /** * 自定义对象 * @author 毛麒添 * HashSet 使用的bean 重写了equals和HashCode方法 */ public class Person1 { private String name; private int age; public Person1() { super(); // TODO Auto-generated constructor stub } public Person1(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 String toString() { return "Person1 [name=" + name + ", age=" + age + "]"; } //使HashSet存储元素唯一 @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) { System.out.println("equals调用了"); if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Person1 other = (Person1) 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; } } public class Demo1_Hashset { public static void main(String[] args) { HashSet hs.add(new Person1("张三", 23)); hs.add(new Person1("张三", 23)); hs.add(new Person1("李四", 24)); hs.add(new Person1("李四", 24)); hs.add(new Person1("李四", 24)); hs.add(new Person1("李四", 24)); System.out.println(hs); } 运行结果如图,达到了不存储重复自定义对象的目的。其实HashSet的下面还有一个LinkedHashSet,底层是链表实现的,是set中唯一一个能保证怎么存就怎么取的集合对象,是HashSet的子类,保证元素唯一,与HashSet原理一样,这里就不多说了。 最后是TreeSet集合,该集合是用来进行排序的,同样也可以保证元素的唯一,可以指定一个顺序, 对象存入之后会按照指定的顺序排列。 指定排序有两种实现: Comparable:集合加入自定义对象的时候,自定义对象需要实现Comparable接口, 实现接口的抽象方法中返回0,则集合中只有一个元素 返回正数,则集合中怎么存则怎么取, 返回负数,集合倒序存储 Comparator(比较器): 创建TreeSet的时候可以制定 一个Comparator 如果传入了Comparator的子类对象, 那么TreeSet就会按照比较器中的顺序排序 add()方法内部会自动调用Comparator接口中compare()方法排序 调用的对象是compare方法的第一个参数,集合中的对象是compare方法的第二个参数 原理: TreeSet底层二叉排序树 返回小的数字存储在树的左边(负数),大的存储在右边(正数),相等则不存(等于0) 在TreeSet集合中如何存取元素取决于compareTo()方法的返回值 下面来看例子: /** * 自定义对象 用于TreeSet * @author 毛麒添 * */ public class Person implements Comparable private String name; private int age; public Person(){ super(); } public Person(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 String toString() { return "Person [name=" + name + ", age=" + age + "]"; } @Override public boolean equals(Object obj) { Person p=(Person) obj; return this.name.equals(p.name)&&this.age==p.age; } @Override public int hashCode() { // TODO Auto-generated method stub return 1; } /*//按照年龄进行排序(TreeSet) @Override public int compareTo(Person o) { int number=this.age-o.age;//年龄是比较的主要条件 //当年龄一样的时候比较名字来确定排序 return number==0?this.name.compareTo(o.name):number; }*/ //按照姓名进行排序(TreeSet) @Override public int compareTo(Person o) { int number=this.name.compareTo(o.name);//姓名是比较的主要条件 //当姓名一样的时候比年龄来确定排序 return number==0?this.age- o.age:number; } //按照姓名长度进行排序(TreeSet) /*@Override public int compareTo(Person o) { int length=this.name.length()-o.name.length();//姓名长度比较的次要条件 int number=length==0?this.name.compareTo(o.name):length;//姓名是比较的次要条件 //比年龄也是次要条件 return number==0?this.age- o.age:number; }*/ } /** * * @author 毛麒添 * TreeSet集合 * 集合加入自定义对象的时候,自定义对象需要实现Comparable接口, * 实现接口的抽象方法中返回0,则集合中只有一个元素 * 返回正数,则集合中怎么存则怎么取, * 返回负数,集合倒序存储 * * 将字符按照长度来进行排序在TreeSet中,需要使用有比较的构造方法进行比较。 */ public class Demo_TreeSet { public static void main(String[] args) { // TODO Auto-generated method stub demo1();//整数存取排序 demo2();//自定义对象排序 //将字符按照长度来进行排序在TreeSet中 TreeSet strLenset.add("aaaaa"); strLenset.add("lol"); strLenset.add("wrc"); strLenset.add("wc"); strLenset.add("b"); strLenset.add("wnnnnnnnnnnn"); System.out.println(strLenset); } private static void demo2() { TreeSet ptreeSet.add(new Person("李四",12)); ptreeSet.add(new Person("李四",16)); ptreeSet.add(new Person("李青",16)); ptreeSet.add(new Person("王五",19)); ptreeSet.add(new Person("赵六",22)); System.out.println(ptreeSet); } private static void demo1() { TreeSet< Integer> treeSet=new TreeSet treeSet.add(1); treeSet.add(1); treeSet.add(1); treeSet.add(3); treeSet.add(3); treeSet.add(3); treeSet.add(2); treeSet.add(2); treeSet.add(2); System.out.println(treeSet); } } //TreeSet 构造器,实现compare对需要存储的字符串进行比较 class compareByLen implements Comparator //按照字符串的长度进行比较,该方法的返回值和继承Comparable的compareTo方法返回值同理。 @Override public int compare(String o1, String o2) { int num=o1.length()-o2.length();//以长度为主要条件 return num==0?o1.compareTo(o2):num;//内容为次要条件 } } 下面是运行截图,其中compareTo的实现方法对几种条件排序进行了实现,具体可以查看Person自定义类中的实现。 单列集合复习就到这里吧。 双列集合 同样的,在复习双列结合之前我们先看看双列集合的继承图。 Map集合的功能梳理: 添加功能 V put(K key,V value):添加元素。 如果键是第一次存储,就直接存储元素,返回null 如果键不是第一次存在,就用值把以前的值替换掉,返回以前的值 删除功能 void clear():移除所有的键值对元素 V remove(Object key):根据键删除键值对元素,并把值返回 判断功能 boolean containsKey(Object key):判断集合是否包含指定的键 boolean containsValue(Object value):判断集合是否包含指定的值 boolean isEmpty():判断集合是否为空 获取功能 Set V get(Object key):根据键获取值 Set Collection 长度功能 int size():返回集合中的键值对的个数 Map类集合也有三种遍历方式: 使用迭代器进行遍历 使用增强For循环来进行遍历 使用Map.Entry来遍历集合中的元素 下面我们来看看如何实现上面三种遍历方式 /** * * @author 毛麒添 * Map 集合的遍历 */ public class Demo { public static void main(String[] args) { Map map.put("张三", 18); map.put("李四", 19); map.put("王五", 20); map.put("赵六", 21); //使用迭代器进行遍历 /*Set Iterator while(iterator.hasNext()){ String key = iterator.next(); Integer i=map.get(key); System.out.println(i); }*/ //使用增强For循环来进行遍历 for (String key :map.keySet()) { Integer integer = map.get(key); System.out.println(integer); } /*---------------------------使用Map.Entry来遍历集合中的元素--------------------------*/ Set /*//使用迭代器来遍历 Iterator while(iterator.hasNext()){ Entry String key = e.getKey();//根据键值对对象获取键 Integer value = e.getValue();//根据键值对对象获取值 System.out.print(key); System.out.println(value); }*/ //使用增强for循环来遍历 for (Entry String key = entry.getKey(); Integer value = entry.getValue(); System.out.print(key); System.out.println(value); } /*---------------------------使用Map.Entry来遍历集合中的元素--------------------------*/ } } LinkHashMap与LinkHashSet一样,怎么存怎么取,保证元素唯一(key 是唯一判定值),由于保证元素唯一,其性能肯定会低一些,这里就不细说了。 TreeMap是双列集合,其实他和TreeSet是很像的,但是双列集合的键是唯一标识,所以TreeMap排序的是每个元素的键。对于存储自定义对象排序,它也有Comparable和Comparator,下面我们来看例子 /** * * @author 毛麒添 * TreeMap * 通TreeSet 原理,存取自定义对象也需要继承Comparable结构, * 或者实现比较器Comparator */ public class Demo6_TreeMap { public static void main(String[] args) { TreeMap @Override public int compare(Student s1, Student s2) { int num=s1.getName().compareTo(s2.getName());//以姓名作为主要比较条件 return num==0?s1.getAge()-s2.getAge():num; } }); tm.put(new Student("张三",13),"杭州"); tm.put(new Student("张三",14), "贺州"); tm.put(new Student("王五",15), "广州"); tm.put(new Student("赵六",16), "深圳"); System.out.println(tm); } } /** * 自定义对象 * @author 毛麒添 * HashMap 存储对象 与 HashSet 同理 需要重写 hashcode 和equals 方法 * TreeMap 实现 Comparable接口 */ public class Student implements Comparable private int age; private String name; public Student(){ super(); } public Student(String name,int age){ this.name=name; this.age=age; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Student [age=" + age + ", name=" + name + "]"; } @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 compareTo(Student o) { int num =this.age-o.age;//以年龄为主要条件 return num==0?this.name.compareTo(o.name):num;//姓名作为次要条件 } } 到这里,Java集合框架的复习基本完成,最后来一个斗地主的例子对集合框架做一个综合应用,只是实现斗地主洗牌和发牌,至于怎么打牌,逻辑复杂,这里不做实现。 /** * * @author 毛麒添 * 模拟斗地主洗牌和发牌,牌排序 * 买一副扑克 * 洗牌 * 发牌 * 看牌 */ public class Doudizhu_progress { public static void main(String[] args) { // TODO Auto-generated method stub //构造一副扑克牌 String[] number={"3","4","5","6","7","8","9","10","J","Q","K","A","2"}; String[]color={"黑桃","红桃","梅花","方块"}; HashMap ArrayList int index=0; //索引 for (String s1 : number) { for (String s2 : color) { pokerMap.put(index,s2.concat(s1)); list.add(index); index++; } } //加入大小王 pokerMap.put(index,"小王"); list.add(index); index++; pokerMap.put(index,"大王"); list.add(index); //洗牌 Collections.shuffle(list); //System.out.println(list); //发牌,3个人玩 加上底牌3张 使用TreeSet 来存放索引,并自动对索引排好序 TreeSet TreeSet TreeSet TreeSet for(int i=0;i if(i>=list.size()-3){//最后三张牌,作为底牌 dipai.add(list.get(i)); }else if(i%3==0){ mao.add(list.get(i)); }else if(i%3==1){ li.add(list.get(i)); }else { huang.add(list.get(i)); } } //看牌 lookPoker(pokerMap,mao,"mao"); lookPoker(pokerMap,li,"li"); lookPoker(pokerMap,huang,"huang"); lookPoker(pokerMap,dipai,"底牌"); } /** * 看牌的方法 * @param pokerMap 存放牌的map * @param mao 该玩家的牌的索引集合 * @param name 玩家名字 */ private static void lookPoker(HashMap TreeSet if(name.equals("底牌")){ System.out.print("地主"+name+"的牌是:"); }else{ System.out.print("玩家"+name+"的牌是:"); } for (Integer integer : mao) { System.out.print(pokerMap.get(integer)+" "); } System.out.println(); } } 运行截图: 写在最后:
if("b".equals(list.get(i))){
list.remove(i--);// i-- 当集合中有重复元素的时候保证要删除的重复元素被删除
}
}
//2.使用迭代器遍历集合
Iterator
while(it.hasNext){
if("b".equals(it.next())){
it.remove();//这里必须使用迭代器的删除方法,而不能使用集合的删除方法,否则会出现并发修改异常(ConcurrentModificationException)
}
}
//使用增强for循环来进行删除
for (String str:list){
if("b".equals(str)){
list.remove("b");//增强for循环底层依赖的是迭代器,而这里删除使用的依旧是集合的删除方法,同理肯定是会出现并发修改异常(ConcurrentModificationException),所以增强for循环一直能用来遍历集合,不能对集合的元素进行删除。
}
}
接下里我们看Set集合,我们知道Set 集合存储无序,无索引,不可以存储重复的对象;我们使用Set集合都是需要去掉重复元素的, 如果在存储的时候逐个equals()比较, 效率较低,哈希算法提高了去重复的效率, 降低了使用equals()方法的次数,其中HashSet底层基于哈希算法,当HashSet调用add方法存储对象,先调用对象的hashCode()方法得到一个哈希值, 然后在集合中查找是否有哈希值相同的对象,如果没有哈希值相同的对象就直接存入集合,如果有哈希值相同的对象, 就和哈希值相同的对象逐个进行equals()比较,比较结果为false就存入, true则不存。下面给出HashSet存储自定义对象的一个例子,自定义对象需要重写hashCode()和equals()方法。
/**
* 自定义对象
* @author 毛麒添
* HashSet 使用的bean 重写了equals和HashCode方法
*/
public class Person1 {
private String name;
private int age;
public Person1() {
super();
// TODO Auto-generated constructor stub
}
public Person1(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 String toString() {
return "Person1 [name=" + name + ", age=" + age + "]";
}
//使HashSet存储元素唯一
@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) {
System.out.println("equals调用了");
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person1 other = (Person1) 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;
}
}
public class Demo1_Hashset {
public static void main(String[] args) {
HashSet
hs.add(new Person1("张三", 23));
hs.add(new Person1("张三", 23));
hs.add(new Person1("李四", 24));
hs.add(new Person1("李四", 24));
hs.add(new Person1("李四", 24));
hs.add(new Person1("李四", 24));
System.out.println(hs);
}
运行结果如图,达到了不存储重复自定义对象的目的。其实HashSet的下面还有一个LinkedHashSet,底层是链表实现的,是set中唯一一个能保证怎么存就怎么取的集合对象,是HashSet的子类,保证元素唯一,与HashSet原理一样,这里就不多说了。
最后是TreeSet集合,该集合是用来进行排序的,同样也可以保证元素的唯一,可以指定一个顺序, 对象存入之后会按照指定的顺序排列。
指定排序有两种实现:
Comparable:集合加入自定义对象的时候,自定义对象需要实现Comparable接口,
实现接口的抽象方法中返回0,则集合中只有一个元素
返回正数,则集合中怎么存则怎么取,
返回负数,集合倒序存储
Comparator(比较器):
创建TreeSet的时候可以制定 一个Comparator
如果传入了Comparator的子类对象, 那么TreeSet就会按照比较器中的顺序排序
add()方法内部会自动调用Comparator接口中compare()方法排序
调用的对象是compare方法的第一个参数,集合中的对象是compare方法的第二个参数
原理:
TreeSet底层二叉排序树
返回小的数字存储在树的左边(负数),大的存储在右边(正数),相等则不存(等于0)
在TreeSet集合中如何存取元素取决于compareTo()方法的返回值
下面来看例子:
/**
* 自定义对象 用于TreeSet
* @author 毛麒添
*
*/
public class Person implements Comparable
private String name;
private int age;
public Person(){
super();
}
public Person(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 String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
@Override
public boolean equals(Object obj) {
Person p=(Person) obj;
return this.name.equals(p.name)&&this.age==p.age;
}
@Override
public int hashCode() {
// TODO Auto-generated method stub
return 1;
}
/*//按照年龄进行排序(TreeSet)
@Override
public int compareTo(Person o) {
int number=this.age-o.age;//年龄是比较的主要条件
//当年龄一样的时候比较名字来确定排序
return number==0?this.name.compareTo(o.name):number;
}*/
//按照姓名进行排序(TreeSet)
@Override
public int compareTo(Person o) {
int number=this.name.compareTo(o.name);//姓名是比较的主要条件
//当姓名一样的时候比年龄来确定排序
return number==0?this.age- o.age:number;
}
//按照姓名长度进行排序(TreeSet)
/*@Override
public int compareTo(Person o) {
int length=this.name.length()-o.name.length();//姓名长度比较的次要条件
int number=length==0?this.name.compareTo(o.name):length;//姓名是比较的次要条件
//比年龄也是次要条件
return number==0?this.age- o.age:number;
}*/
}
/**
*
* @author 毛麒添
* TreeSet集合
* 集合加入自定义对象的时候,自定义对象需要实现Comparable接口,
* 实现接口的抽象方法中返回0,则集合中只有一个元素
* 返回正数,则集合中怎么存则怎么取,
* 返回负数,集合倒序存储
*
* 将字符按照长度来进行排序在TreeSet中,需要使用有比较的构造方法进行比较。
*/
public class Demo_TreeSet {
public static void main(String[] args) {
// TODO Auto-generated method stub
demo1();//整数存取排序
demo2();//自定义对象排序
//将字符按照长度来进行排序在TreeSet中
TreeSet
strLenset.add("aaaaa");
strLenset.add("lol");
strLenset.add("wrc");
strLenset.add("wc");
strLenset.add("b");
strLenset.add("wnnnnnnnnnnn");
System.out.println(strLenset);
}
private static void demo2() {
TreeSet
ptreeSet.add(new Person("李四",12));
ptreeSet.add(new Person("李四",16));
ptreeSet.add(new Person("李青",16));
ptreeSet.add(new Person("王五",19));
ptreeSet.add(new Person("赵六",22));
System.out.println(ptreeSet);
}
private static void demo1() {
TreeSet< Integer> treeSet=new TreeSet
treeSet.add(1);
treeSet.add(1);
treeSet.add(1);
treeSet.add(3);
treeSet.add(3);
treeSet.add(3);
treeSet.add(2);
treeSet.add(2);
treeSet.add(2);
System.out.println(treeSet);
}
}
//TreeSet 构造器,实现compare对需要存储的字符串进行比较
class compareByLen implements Comparator
//按照字符串的长度进行比较,该方法的返回值和继承Comparable的compareTo方法返回值同理。
@Override
public int compare(String o1, String o2) {
int num=o1.length()-o2.length();//以长度为主要条件
return num==0?o1.compareTo(o2):num;//内容为次要条件
}
}
下面是运行截图,其中compareTo的实现方法对几种条件排序进行了实现,具体可以查看Person自定义类中的实现。
单列集合复习就到这里吧。
双列集合
同样的,在复习双列结合之前我们先看看双列集合的继承图。
Map集合的功能梳理:
添加功能
V put(K key,V value):添加元素。
如果键是第一次存储,就直接存储元素,返回null
如果键不是第一次存在,就用值把以前的值替换掉,返回以前的值
删除功能
void clear():移除所有的键值对元素
V remove(Object key):根据键删除键值对元素,并把值返回
判断功能
boolean containsKey(Object key):判断集合是否包含指定的键
boolean containsValue(Object value):判断集合是否包含指定的值
boolean isEmpty():判断集合是否为空
获取功能
Set
V get(Object key):根据键获取值
Set
Collection
长度功能
int size():返回集合中的键值对的个数
Map类集合也有三种遍历方式:
使用迭代器进行遍历
使用增强For循环来进行遍历
使用Map.Entry来遍历集合中的元素
下面我们来看看如何实现上面三种遍历方式
/**
*
* @author 毛麒添
* Map 集合的遍历
*/
public class Demo {
public static void main(String[] args) {
Map
map.put("张三", 18);
map.put("李四", 19);
map.put("王五", 20);
map.put("赵六", 21);
//使用迭代器进行遍历
/*Set
Iterator
while(iterator.hasNext()){
String key = iterator.next();
Integer i=map.get(key);
System.out.println(i);
}*/
//使用增强For循环来进行遍历
for (String key :map.keySet()) {
Integer integer = map.get(key);
System.out.println(integer);
}
/*---------------------------使用Map.Entry来遍历集合中的元素--------------------------*/
Set
/*//使用迭代器来遍历
Iterator
while(iterator.hasNext()){
Entry
String key = e.getKey();//根据键值对对象获取键
Integer value = e.getValue();//根据键值对对象获取值
System.out.print(key);
System.out.println(value);
}*/
//使用增强for循环来遍历
for (Entry
String key = entry.getKey();
Integer value = entry.getValue();
System.out.print(key);
System.out.println(value);
}
/*---------------------------使用Map.Entry来遍历集合中的元素--------------------------*/
}
}
LinkHashMap与LinkHashSet一样,怎么存怎么取,保证元素唯一(key 是唯一判定值),由于保证元素唯一,其性能肯定会低一些,这里就不细说了。
TreeMap是双列集合,其实他和TreeSet是很像的,但是双列集合的键是唯一标识,所以TreeMap排序的是每个元素的键。对于存储自定义对象排序,它也有Comparable和Comparator,下面我们来看例子
/**
*
* @author 毛麒添
* TreeMap
* 通TreeSet 原理,存取自定义对象也需要继承Comparable结构,
* 或者实现比较器Comparator
*/
public class Demo6_TreeMap {
public static void main(String[] args) {
TreeMap
@Override
public int compare(Student s1, Student s2) {
int num=s1.getName().compareTo(s2.getName());//以姓名作为主要比较条件
return num==0?s1.getAge()-s2.getAge():num;
}
});
tm.put(new Student("张三",13),"杭州");
tm.put(new Student("张三",14), "贺州");
tm.put(new Student("王五",15), "广州");
tm.put(new Student("赵六",16), "深圳");
System.out.println(tm);
}
}
/**
* 自定义对象
* @author 毛麒添
* HashMap 存储对象 与 HashSet 同理 需要重写 hashcode 和equals 方法
* TreeMap 实现 Comparable接口
*/
public class Student implements Comparable
private int age;
private String name;
public Student(){
super();
}
public Student(String name,int age){
this.name=name;
this.age=age;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student [age=" + age + ", name=" + name + "]";
}
@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 compareTo(Student o) {
int num =this.age-o.age;//以年龄为主要条件
return num==0?this.name.compareTo(o.name):num;//姓名作为次要条件
}
}
到这里,Java集合框架的复习基本完成,最后来一个斗地主的例子对集合框架做一个综合应用,只是实现斗地主洗牌和发牌,至于怎么打牌,逻辑复杂,这里不做实现。
/**
*
* @author 毛麒添
* 模拟斗地主洗牌和发牌,牌排序
* 买一副扑克
* 洗牌
* 发牌
* 看牌
*/
public class Doudizhu_progress {
public static void main(String[] args) {
// TODO Auto-generated method stub
//构造一副扑克牌
String[] number={"3","4","5","6","7","8","9","10","J","Q","K","A","2"};
String[]color={"黑桃","红桃","梅花","方块"};
HashMap
ArrayList
int index=0; //索引
for (String s1 : number) {
for (String s2 : color) {
pokerMap.put(index,s2.concat(s1));
list.add(index);
index++;
}
}
//加入大小王
pokerMap.put(index,"小王");
list.add(index);
index++;
pokerMap.put(index,"大王");
list.add(index);
//洗牌
Collections.shuffle(list);
//System.out.println(list);
//发牌,3个人玩 加上底牌3张 使用TreeSet 来存放索引,并自动对索引排好序
TreeSet
TreeSet
TreeSet
TreeSet
for(int i=0;i if(i>=list.size()-3){//最后三张牌,作为底牌 dipai.add(list.get(i)); }else if(i%3==0){ mao.add(list.get(i)); }else if(i%3==1){ li.add(list.get(i)); }else { huang.add(list.get(i)); } } //看牌 lookPoker(pokerMap,mao,"mao"); lookPoker(pokerMap,li,"li"); lookPoker(pokerMap,huang,"huang"); lookPoker(pokerMap,dipai,"底牌"); } /** * 看牌的方法 * @param pokerMap 存放牌的map * @param mao 该玩家的牌的索引集合 * @param name 玩家名字 */ private static void lookPoker(HashMap TreeSet if(name.equals("底牌")){ System.out.print("地主"+name+"的牌是:"); }else{ System.out.print("玩家"+name+"的牌是:"); } for (Integer integer : mao) { System.out.print(pokerMap.get(integer)+" "); } System.out.println(); } } 运行截图: 写在最后:
if(i>=list.size()-3){//最后三张牌,作为底牌
dipai.add(list.get(i));
}else if(i%3==0){
mao.add(list.get(i));
}else if(i%3==1){
li.add(list.get(i));
}else {
huang.add(list.get(i));
}
}
//看牌
lookPoker(pokerMap,mao,"mao");
lookPoker(pokerMap,li,"li");
lookPoker(pokerMap,huang,"huang");
lookPoker(pokerMap,dipai,"底牌");
}
/**
* 看牌的方法
* @param pokerMap 存放牌的map
* @param mao 该玩家的牌的索引集合
* @param name 玩家名字
*/
private static void lookPoker(HashMap
TreeSet
if(name.equals("底牌")){
System.out.print("地主"+name+"的牌是:");
}else{
System.out.print("玩家"+name+"的牌是:");
}
for (Integer integer : mao) {
System.out.print(pokerMap.get(integer)+" ");
}
System.out.println();
}
}
运行截图:
写在最后:
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~