注册登录
定义一个用户类:
public class PersonTest { //成员变量对外不可见 private String name; private String password; public PersonTest(){} public PersonTest(String name, String password){ this.name = name; this.password = password; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
定义一个用户操作接口:
//用户操作接口 //如果后续需要修改用户操作,直接实现接口即可 public interface User { //登录 public abstract boolean islogin(String name, String password); //注册 public abstract void isRegister(PersonTest pt); }
定义一个用户操作实现类:
import java.util.ArrayList; //用户实际操作类 public class UserTest implements User{ //存储用户名和密码的集合 private static ArrayList<PersonTest> ap = new ArrayList<PersonTest>(); //登录判断操作 public boolean islogin(String name, String password) { boolean flag = false; for(PersonTest pt : ap){ if(pt.getName().equals(name) && pt.getPassword().equals(password)){ flag = true; break; } } return flag; } //添加用户 public void isRegister(PersonTest pt) { ap.add(pt); } }
用户测试类:
//用户测试类 import java.util.Scanner; public class PersonDemo { public static void main(String[] args) { while (true) { System.out.println("--------------欢迎光临--------------"); System.out.println("1 登录"); System.out.println("2 注册"); System.out.println("3 退出"); // 用户输入 Scanner sc = new Scanner(System.in); // 输入 1 2 3或者其他选择退出 注册 登录选择 String ss = sc.nextLine(); // 用户操作类 UserTest ut = new UserTest(); switch (ss) { // 选择1,则用户登录操作 case "1": System.out.println("--------------登录界面--------------"); System.out.println("请输入用户名: "); String name = sc.nextLine(); System.out.println("请输入密码:"); String password = sc.nextLine(); boolean flag = ut.islogin(name, password); if (flag) { System.out.println("--------------登录成功--------------"); } else { System.out.println("--------------登录失败--------------"); } break; // 选择2,则用户注册操作 case "2": System.out.println("--------------注册界面--------------"); System.out.println("请输入用户名: "); String newname = sc.nextLine(); System.out.println("请输入密码:"); String newpassword = sc.nextLine(); //把注册输入的用户名和密码存入对象中 PersonTest pt = new PersonTest(); pt.setName(newname); pt.setPassword(newpassword); //把对象存入集合中,就注册成功了 ut.isRegister(pt); System.out.println("--------------注册成功--------------"); break; // 选择3,或者其他则退出 case "3": System.out.println("--------------谢谢光临--------------"); System.exit(0); break; default: System.out.println("--------------谢谢光临--------------"); System.exit(0); break; } } } }
循环中断标签:
h: while (true) { Scanner sc = new Scanner(System.in); UserTest ut = new UserTest(); switch (ss) { case "1": break; case "2": break; case "3": //使用中断标签退出 break h; default: System.exit(0); break; } }
Set
import java.util.HashSet; public class SetTest { public static void main(String[] args) { // TODO 自动生成的方法存根 HashSet<String> hs = new HashSet<String>(); //依赖hashCode()和euqals(),String()类重写了这两个方法 //如果存入对象,因为这个方法依赖hashCode()和euqals()方法 //而如果类中没有重写euqals()和hashCode()方法,所以默认使用Object类的 //这个时候它们的哈希码是不一样的,所以都可以存入。 hs.add("hello"); hs.add("java"); hs.add("world"); hs.add("hello"); for(String s : hs){ System.out.println(s); } }
//重写了euqals()和hashCode()方法只会存入对象,这两个方法可以自动生成 HashSet<Student> hs2 = new HashSet<Student>(); Student s1 = new Student("zed1", 1); Student s2 = new Student("zed1", 1); Student s3 = new Student("zed2", 2); Student s4= new Student("zed2", 3); Student s5 = new Student("zed3", 3); hs2.add(s1); hs2.add(s2); hs2.add(s3); hs2.add(s4); hs2.add(s5); for(Student s : hs2){ System.out.println(s.getName() + "------" + s.getAge()); }
import java.util.LinkedHashSet; /*LinkedHashSet:底层数据结构由哈希表和链表组成 哈希表保证元素的唯一性 链表保证元素有序(存储和取出一致)*/ public class LinkedListTest { public static void main(String[] args) { LinkedHashSet<String> ll = new LinkedHashSet<String>(); ll.add("hello"); ll.add("world"); ll.add("java"); for (String s : ll) { System.out.println(s); } } }
TreeSet
TreeSet<Integer> ts = new TreeSet<Integer>(); ts.add(10); ts.add(9); ts.add(13); ts.add(10); for(int i : ts){ //有序唯一,默认自然排序 System.out.println(i); }
TreeSet:能够对元素按照某种规则进行排序
排序方式:
自然排序 让元素所属类实现自然排序接口Comparable
比较器排序 让集合的构造方法接口一个比较器接口的子类对象Comparator
TreeSet特点:排序唯一
TreeSet:底层是二叉树结构(红黑树是一种自平衡的二叉树)、
元素如何存储进去?
第一个元素存储的时候,直接作为根节点存储
第二个元素开始,每个元素从根节点开始比较
大 就作为右孩子
小 就作为左孩子
相等 就不管
取出:从根节点开始,按左、中、右开始,从左开始取出
如果一个类的元素要想能够进行自然排序,就必须实现自然排序接口
对象类 Student implements Comparable<Student(要比较的类)>
//分清主要条件年龄,次要条件姓名,年龄比较完相等,就比较姓名 public int compareTo(Student s){ int num = this.age - s.age; //如果年龄相等,则比较姓名,如果姓名也是相等的,则num2等于0,不管她 int num2 = num == 0 ? this.name.compareTo(s.name) : num; return num2; }
//如果主要条件是姓名条件,则应该这样: 排序实际上是在存入的时候进行排序,取出按存入的排序取出 //比较姓名长度
//如果想按从高到底的顺序排 int num = s.name.length() - this.name.length();更换一下运算的顺序就可以 int num = this.name.length() - s.name.length(); //比较姓名 int num2 = num == 0 ? this.name.comparableTo(s.name) : num; //比较年龄 int num3 = num2 == 0 ? this.age - s.age : num2; return num3;
比较器排序
//比较器排序,构造方法:TreeSet(Comparator<? super E> comparator),实现Comparator接口 TreeSet<String> ts = new TreeSet<String>(new Comparator<String>(){ //具体实现
public int compare(String 1, String 2){
比较实现
} }); //或者通过另写一个实现类,在把实现类对象传入到构造方法中
//降序排列 TreeSet<Integer> ts = new TreeSet<Integer>(new Comparator<Integer>(){ public int compare(Integer In1, Integer In2){ //In1大于In2,默认返回正数,In2存储在In1的左边。 //现在返回为负,则In2存储在In1的右边
//默认比较中返回值大于0,就往右边放;小于0,就往左边放。两者比较大的放右边,小的放左边。取出从左往右取。 if(In1 - In2 > 0){ return -1; }else if(In1 - In2 < 0){ return 1; }else{ return 0; } } });
Map
Map集合的特点:
将键映射到值的对象,一个映射不能包含重复的键,每个键只能映射到一个值
Map和Collection的区别
Map集合的存储元素是承兑出现的,Map集合的键是唯一的,值是可重复的
Collection集合存储元素是单独出现的,Collection的Set是唯一的,List是可重复的。
迭代遍历的两种方式:根据键找值(keySet()提取键,然后找值)和根据键值对找键和值(Set<Map.Entry<K,V>> entrySet()方法提取键值对映射对象,然后通过getKey()和getValue()找到键和值)
import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; public class MapTest { public static void main(String[] args) { Map<Integer, String> m = new HashMap<Integer, String>(); //键是唯一的,所以只会传入一个[1, "zed1"]
//迭代遍历的两种方式:根据键找值和根据键值对找键和值 m.put(1, "zed1"); m.put(1, "zed1"); m.put(2, "zed2"); m.put(3, "zed3"); m.put(4, "zed4"); m.put(5, "zed5"); //Set<Map.Entry<K,V>> entrySet() 返回此映射中包含的映射关系的 Set 视图。返回的是一个包含在Set集合中的Map对象 //两种方式输出集合对象,一种是直接输出,一种是通过getKey()和getValue()方法迭代 System.out.println(m.entrySet());
Set<Map.Entry<K,V>> s = m.entrySet();
for(Map.Entry<K,V> me : s){
System.out.println(me.getKey() + "-----" + me.getValue());
} //第二种输出映射关系的方式,使用get()方法
//提取键,然后根据键找值 Set<Integer> hs = m.keySet(); //如果i的初始值为0,则get(0)为空值,size()第一位是1,不是0; //而且使用for循环的话,如果键不是数字元素,则无法处理 for(int i = 1; i <= hs.size(); i++){ System.out.println(m.get(i)); } System.out.println("----------------------"); //增强for for(int i : hs){ System.out.println(i + m.get(i)); } System.out.println("----------------------"); //迭代器 Iterator<Integer> it = hs.iterator(); while(it.hasNext()){ System.out.println(it.next() + m.get(it.next())); }
public class MapTest { public static void main(String[] args) { Map<Integer, String> m = new HashMap<Integer, String>(); m.put(1, "zed1"); m.put(1, "zed1"); m.put(2, "zed2"); m.put(3, "zed3"); m.put(4, "zed4"); m.put(5, "zed5"); // boolean containsKey(Object key) 如果此映射包含指定键的映射关系,则返回 true。 System.out.println(m.containsKey(3)); // boolean containsValue(Object value) 如果此映射将一个或多个键映射到指定值,则返回 true。 System.out.println(m.containsValue("zed2")); //清空 m.clear(); System.out.println(m.entrySet()); } }
public class MapTest { public static void main(String[] args) { Map<Integer, String> m = new HashMap<Integer, String>(); m.put(1, "zed1"); m.put(1, "zed1"); m.put(2, "zed2"); m.put(3, "zed3"); m.put(4, "zed4"); m.put(5, "zed5"); /* Collection<V> values() 返回此映射中包含的值的 Collection 视图。*/ Collection<String> c = m.values(); System.out.println(c); } }
public class MapTest { public static void main(String[] args) { Map<Integer, String> m = new HashMap<Integer, String>(); /* * put()方法: * 存入键值对,如果此键值中以前有一个键映射,则替换掉旧的值,并返回就值 * 如果键之前不存在,则添加键值对映射,返回null。 * */ System.out.println(m.put(1, "zed1")); System.out.println(m.put(1, "zed2"));
//返回[1, zed2] System.out.println(m.entrySet()); } }
//删除映射,remove()键,返回值 System.out.println(m.remove(1));
HashMap<Integer> hm = HashMap<Integer>(); hm.put(007); //下面这句会报错,因为0开头是八进制,不能出现8以上数字 hm.put(008);
HashMap传入对象键的问题
是基于哈希表的Map接口实现
哈希表的作用是用来保证键的唯一性的。
public class StudentTest { // 变量私有,给出get方法提供变量 // 某些属性成员变量不要让外界任意访问 private String name; private int age; public StudentTest() { } public StudentTest(String name, int age) { 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; } public String toString() { return "Student [name=" + name + ", age=" + age + "]"; } /* * 放开下面的注释,HashMap传入集合对象就会正确处理是否重复的问题 * * * 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; StudentTest other = (StudentTest) 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; }*/ } //---------------------------------------------------- import java.util.HashMap; import java.util.Set; public class MapTest2 { public static void main(String[] args) { HashMap<StudentTest, String> hs = new HashMap<StudentTest, String>(); //下面重复元素对象依然会传入到Map集合中,因为HashMap依赖的是hashcode()和euqals()方法 //而StudentTest类没有重写这两个方法,所以调用的是Object类的。 //重写了这两个方法,就会正确传入集合对象 StudentTest st1 = new StudentTest("zed1", 1); StudentTest st2 = new StudentTest("zed2", 2); StudentTest st3 = new StudentTest("zed3", 3); StudentTest st4 = new StudentTest("zed4", 4); StudentTest st5 = new StudentTest("zed4", 5); StudentTest st6 = new StudentTest("zed1", 1); hs.put(st1, "劫1"); hs.put(st2, "劫2"); hs.put(st3, "劫3"); hs.put(st4, "劫4"); hs.put(st5, "劫5"); hs.put(st6, "劫6"); Set<StudentTest> s = hs.keySet(); for(StudentTest stu : s ){ String stuName = stu.getName(); int stuAge = stu.getAge(); String stuValue = hs.get(stu); System.out.println(stuName + "---" + stuAge + "---" + stuValue); } } }
LinkedHashMap
是Map接口的哈希表(保证键的唯一性)和链接列表(保证键的(存储和取出的顺序一致)有序)实现,具有可预知的迭代顺序。
Map嵌套
public class HashMapDemo2 { public static void main(String[] args) { // 创建集合对象 HashMap<String, HashMap<String, Integer>> czbkMap = new HashMap<String, HashMap<String, Integer>>(); // 创建集合对象 HashMap<String, Integer> jcMap = new HashMap<String, Integer>(); // 添加元素 jcMap.put("zed1", 20); jcMap.put("zed2", 22); // 添加到大集合 czbkMap.put("jc", jcMap); // 创建集合对象 HashMap<String, Integer> jyMap = new HashMap<String, Integer>(); // 添加元素 jyMap.put("akl1", 21); jyMap.put("akl2", 23); // 添加到大集合 czbkMap.put("jy", jyMap); //遍历集合 Set<String> czbkMapSet = czbkMap.keySet(); for(String czbkMapKey : czbkMapSet){ System.out.println(czbkMapKey); HashMap<String, Integer> czbkMapValue = czbkMap.get(czbkMapKey); Set<String> czbkMapValueSet = czbkMapValue.keySet(); for(String czbkMapValueKey : czbkMapValueSet){ Integer czbkMapValueValue = czbkMapValue.get(czbkMapValueKey); System.out.println("\t"+czbkMapValueKey+"---"+czbkMapValueValue); } } }
Hashtable:线程安全,效率低,不允许键和null值
HashMap:线程不安全,效率高,允许null和null值
Hashtable:线程安全,效率低,不允许键和null值
HashMap:线程不安全,效率高,允许null和null值
Collection:是单列集合的顶层接口,有子接口List和Set
Collections:是针对集合操作的工具类,有对集合进行排序和二分查找方法。此类完全由在 collection 上进行操作或返回 collection 的静态方法组成
Comparable<T>:有compareTo(T o)方法,一般用于直接在实现对象类中重写:此接口强行对实现它的每个类的对象进行整体排序
Comparator<T>:有compare(T o1, T o2)方法,一般用于直接在集合中使用,内部类的形式。强行对某个对象 collection 进行整体排序 的比较函数
如果同时有自然排序和比较器排序,排序以比较器为主。