目录
一、LinkedList实现堆栈
1、实例化链表
// 链表实例化 private LinkedList link = new LinkedList();
2、压栈
/** * 压栈 * @param obj */ public void push(Object obj) { // 每次都是添加第一个 link.addFirst(obj); }
3、出栈
/** * 出栈 * @return */ public Object pop() { // 获取顶栈 Object first = link.getFirst(); // 移除 link.removeFirst(); // 返回 return first; }
4、计算堆栈的数量
/** * 计算堆栈的数量 * @return */ public int size() { return link.size(); }
5、实例化测试
public static void main(String[] args) { // 初始化 MyStack stack = new MyStack(); // 压栈 stack.push("a"); stack.push("b"); stack.push("c"); stack.push("d"); stack.push("e"); // 循环 while (stack.size() != 0) { System.out.println(stack.pop()); } }
6、结果显示:
e d c b a
二、Set接口下的实现类
1、HashSet
(1)无序
无序指的是插入的顺序与取出的顺序不一致(从输出结果可以看到)
Set<String> set = new HashSet<String>(); set.add("a"); set.add("d"); set.add("c"); set.add("b"); for (String s : set) { System.out.println(s); }
结果显示:
在对象进入HashSet内部时,会使用对象内部HashCode方法计算hash值后自动进行排序, 所以读取的是经过内部排序后的数据,所以存入的顺序会与取出的顺序有不同(内部通过排序重 新整理了元素的位置),并且在数据没变的情况下,每次数据输出结果都是一样的顺序
(2)不重复
HashSet底层数据结构是哈希表, HashSet不是线程安全的,但是效率高,同时集合元素可以是null
Set<Student> set=new HashSet<>(); set.add(new Student(1,"zs",17,"女")); set.add(new Student(2,"ls",14,"男")); set.add(new Student(3,"ww",17,"男")); set.add(new Student(1,"zs",18,"女")); //equals方法默认比较的是Object类型,而Object是引用类型,比较的是内存地址 //重写equals方法,先比较hashcode值,再比较equals /*Student stu=new Student(); stu.equals(null);*/ set.forEach(System.out::println); System.out.println("-------------------");
通过两个对象 hashCode() 方法拿到哈希值,如果两个哈希值相同,再调用 equals() 方法比较 如果都相同,则认定为同一个元素,无法存入
结果显示:
Student [sid=3, sname=ww, sage=17, ssex=男] Student [sid=1, sname=zs, sage=18, ssex=女] Student [sid=1, sname=zs, sage=17, ssex=女] Student [sid=2, sname=ls, sage=14, ssex=男]
HashSet保证元素唯一性是靠元素重写hashCode()和equals()方法来保证的,如果不重写则无法保证
重写hashCode()和equals()方法:
@Override public int hashCode() { final int prime = 31; int result = 1; //只比较学号 //result = prime * result + sage; result = prime * result + sid; //result = prime * result + ((sname == null) ? 0 : sname.hashCode()); //result = prime * result + ((ssex == null) ? 0 : ssex.hashCode()); return result; } @Override public boolean equals(Object obj) { //true:已存在 //false:不存在,允许添加 //当前对象是否与obj对象相同 if (this == obj) return true; //obj对象为空 if (obj == null) return false; //当前对象类型不等于obj对象类型 if (getClass() != obj.getClass()) return false; return true; }
结果显示:
Student [sid=1, sname=zs, sage=17, ssex=女] Student [sid=3, sname=ww, sage=17, ssex=男] Student [sid=2, sname=ls, sage=14, ssex=男]
2、TreeSet
(1)有序
底层数据结构是二叉树,集合中元素唯一,并且可以对元素进行排序
TreeSet<String> set=new TreeSet<String>(); set.add("jack"); set.add("rose"); set.add("alien"); for (String s : set) { System.out.println(s); }
结果显示:
(2)排序方式:自然排序
让需要排序的类实现 Comparable 接口,重写方法 (因为String实现了这个接口,所以上面的数据是有 序的)
如果返回值>0,他大 如果返回值=0,相等 如果返回值<0,我大
将代码修改为按照学号排序:
@Override public int compareTo(Student o) { // 降序 return -(this.getSid()-o.getSid()); }
实例化测试:
//自然比较接口测试 Set<Student> set=new TreeSet<>(); set.add(new Student(2,"zs",17,"女")); set.add(new Student(3,"ls",13,"男")); set.add(new Student(1,"ww",15,"女")); set.forEach(System.out::println);
结果显示:
Student [sid=3, sname=ls, sage=13, ssex=男] Student [sid=2, sname=zs, sage=17, ssex=女] Student [sid=1, sname=ww, sage=15, ssex=女] -------------
(3)比较器排序
定义一个比较器(实现Comparator接口)重写compare方法::
package com.lixiangning.utils; import java.util.Comparator; import com.lixiangning.entity.Student; /** * 根据姓名比较,进行降序 * @author Administrator */ public class NameComparator implements Comparator<Student> { @Override public int compare(Student a, Student b) { return -(a.getSname().hashCode()-b.getSname().hashCode()); } }
实例化测试:
//比较器测试 Set<Student> set2=new TreeSet<>(new NameComparator()); set2.add(new Student(2,"zs",17,"女")); set2.add(new Student(3,"ls",13,"男")); set2.add(new Student(1,"ww",15,"女")); set2.forEach(System.out::println);
根据姓名降序的结果显示:
Student [sid=2, sname=zs, sage=17, ssex=女] Student [sid=1, sname=ww, sage=15, ssex=女] Student [sid=3, sname=ls, sage=13, ssex=男]