JAVA 笔记(十)
- 重写equles()代码: 以学生类student为例
Public Boolean equles(object obj){ If(this==obj){ Return ture; }
if(!(obj instanceof(Student){ Return flase; } Studetn s=(Student)obj; Return this.name.equals(s.name)&&this.age==s.age; }
- Hashcode重写的时候如果返回相同的数字,那么效率就非常的低,为了解决这个办法,我们得就绝办法就是将对象的成员变量值进行相加,如果是基本数据类型,就直接相加,如果是引用类型就用哈希值。【基本数据类型后面乘以个正数更好】。
- Hashset的底层数据结构是哈希表。
- LinkedHashset:底层数据结构有哈希表和链表组成(它是一种特殊的hashset集合的子类)哈希表:保证了元素的唯一性。链表:保证了元素有序(存储和取出一样)
- TreeSET:能够对元素按照某种规则进行排序A;自然排序B;比较器排序【该类是set类的子类】。二者的使用取决于构造方法的不同。
- Treeset的比较是依赖于元素的Compareto()方法,而这个方法是定义在Comparable接口里面的,所以要想实现该方法,就必须实现该接口,该接口表示的是自然排序。
- Treeset底层数据结构是二叉树结构(是一种自平衡的二叉树)按照左中(根)右的遍历取出的。大于零往右,小于零往左,等于零不进来。
- 要想实现自然排序就得实现comparable接口,然后重写该接口中的compareto()方法。该方法的返回值是int类型,主要看结果与零比较。
- 自然排序既要分析主要条件也要分析次要条件,因为有时主要条件并不一定能够判断出来理想的结果。
- 参数一个接口其实传递的是该接口的实现类,如果仅用一次,那么就可以用匿名内部类完成)。
- Treeset集合保证元素排序和唯一性的原理:唯一性:是根据比较的返回值是否是0而决定的。排序:A;自然排序(元素具备比较性)让元素所属的类实现自然排序接口comparable.B;比较器排序(集合具备比较性)让集合的构造方法接收一个比较器接口的子类对象comparator.(重写compare()方法)
- 集合的总结如下
Collection
|--List 有序,可重复
|--ArrayList
底层数据结构是数组,查询快,增删慢。
线程不安全,效率高
|--Vector
底层数据结构是数组,查询快,增删慢。
线程安全,效率低
|--LinkedList
底层数据结构是链表,查询慢,增删快。
线程不安全,效率高
|--Set 无序,唯一
|--HashSet
底层数据结构是哈希表。
如何保证元素唯一性的呢?
依赖两个方法:hashCode()和equals()
开发中自动生成这两个方法即可
|--LinkedHashSet
底层数据结构是链表和哈希表
由链表保证元素有序
由哈希表保证元素唯一
|--TreeSet
底层数据结构是红黑树。
如何保证元素排序的呢?
自然排序
比较器排序
如何保证元素唯一性的呢?
根据比较的返回值是否是0来决定
- 针对Collection集合我们到底使用谁呢
唯一吗?
是:Set
排序吗?
是:TreeSet
否:HashSet
如果你知道是Set,但是不知道是哪个Set,就用HashSet。
否:List
要安全吗?
是:Vector
否:ArrayList或者LinkedList
查询多:ArrayList
增删多:LinkedList
如果你知道是List,但是不知道是哪个List,就用ArrayList。
如果你知道是Collection集合,但是不知道使用谁,就用ArrayList。
如果你知道用集合,就用ArrayList。
- 生成1-20之间十个不同的随机数
import java.util.Random; import java.util.TreeSet; public class Demo { public static void main(String[] args) { Random r=new Random(); TreeSet<Integer> ts=new TreeSet<Integer>(); while(ts.size()<10){ int number=r.nextInt(20)+1; ts.add(number); } for(Integer t:ts){ System.out.println(t); } } }
- 按年龄排序由高到低排序的代码
package hhxxv; public class Person implements Comparable<Person>{ private String name; private int age; /** * @param name * @param age */ public Person(String name, int age) { super(); this.name = name; this.age = age; } public Person() { super(); // TODO Auto-generated constructor stub } 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 int compareTo(Person p){//实现comparable接口中的方法 int num=p.age-this.age;//如果想从小到大,将二者顺序改一下即可 int num1=num==0?this.name.compareTo(p.name):num; return num1; } @Override public String toString() {//重写totring()方法。要不然是父类object中的该方法 return name + "--------- age=" + age ; } } package hhxxv; import java.util.TreeSet; public class Demo { public static void main(String[] args) { TreeSet<Person> ts=new TreeSet<Person>(); Person p1=new Person("zhangsan",30); Person p2=new Person("zhangsan",30); Person p3=new Person("zhangn",30); Person p4=new Person("lisi",30); Person p5=new Person("wangyu",67); Person p6=new Person("jiji",30); Person p7=new Person("zhhgsan",78); Person p8=new Person("zjksan",45); ts.add(p1);ts.add(p2); ts.add(p3);ts.add(p4);ts.add(p5);ts.add(p6);ts.add(p7);ts.add(p8); for(Person p:ts){ System.out.println(p); } } }
Map集合的特点:将键映射到值得对象,一个映射不能包含重复的键,每个键最多只能映射到一个值。
- Map和collection的区别:map集合存储的元素是成对出现的,它的键是唯一的,但是值可以重复。Collection集合存储的元素是单独出现的,collection的儿子set是唯一的,List是可以重复的。Map集合的数据机构针对键有效,跟值无关。Collection集合的数据结构是针对元素有效。【可以把键看成set集合,值看做是list集合】。
- Map集合中的put()方法需要注意的地方:如果键是第一次存储,就直接存储元素,返回null,如果键不是第一次存储,就用新值把以前的值替换掉,返回以前的值。【map集合中的get()方法是通过建找到值】。
- Map集合的遍历:第一步:获取所有的键。第二步:遍历键的集合,获取得到每一个键。第三部:根据键去找值。
- Map集合的高级遍历:第一步:获取所有键值对对象的集合。第二步:遍历键值对对象的集合,得到每一个键值对对象。第三部:根据键值对对象获取键和值。Entryset();
- Hashmap是基于哈希表的map接口实现。哈希表的作用是用来保证键的唯一性。(底层依赖hashcode()和equals()方法)
- LinkedHahmap(该类是hashmap的子类):是map接口的哈希表和链表实现,具有可预知的迭代顺序。由哈希表保证唯一性,由链表保证有序性(这里的有序指的是存储顺序和取出顺序一致)。
- Treemap:是基于红黑树(平衡二叉树)的map接口的实现。(能排序,键唯一)
- 哈希系类注意hashcode()和equals()方法。树系列注意比较接口的实现。
- Map系列的键相同,值覆盖不要忘了。
- Map遍历的代码
package lianxi.hashmap; import java.util.HashMap; import java.util.Map; import java.util.Set; public class Demo { public static void main(String[] args) { Map<String,String> hh=new HashMap<String,String>(); hh.put("001", "张三"); hh.put("001", "张三"); hh.put("002", "张三"); hh.put("003", "李四"); hh.put("004", "王五"); Set<String> set=hh.keySet(); for(String s:set){ String value=hh.get(s); System.out.println(s+"----------"+value); } System.out.println("------------------------------------"); Set<Map.Entry<String,String>> jj=hh.entrySet(); for(Map.Entry<String,String> ko:jj){ String key=ko.getKey(); String value=ko.getValue(); System.out.println(key+"-------------"+value); } } }
- 自动拆装箱并不只是int类型,其他的基本数据类型也可以。
- Hashtable【这是一个命名不规范的类,1.0的时候就有了】。
- Hashtable:线程安全,效率低,不允许键为null和null值;HashMap:线程不安全,效率高,允许null键和null值。【其余二者差不多,其实HashMap(1.2版本)就是来代替Hashtable的(1.0版本,最早的)】
- Collections:是针对集合(排序,反转等,这里排序的话,该集合必须可以比较,也就是实现comparable接口或者compartor接口等)操作的工具类,都是静态方法。而Collecction是个集合接口。【单列集合的顶层接口】要注意二者的区别。
- 用TreeMap统计每一个字符的个数
package hhxy.edu; import java.util.Scanner; import java.util.Set; import java.util.TreeMap; public class CharCount { public static void main(String[] args) { Scanner sc = new Scanner(System.in); TreeMap<Character, Integer> tm = new TreeMap<Character, Integer>(); System.out.println("请输入一个字符串"); String str = sc.nextLine(); char[] ch = str.toCharArray(); for (char c : ch) { //Set<Character> set = tm.keySet();这时候集合中还没有键,所以这时不用获取键,获取就会出错。 Integer value = tm.get(c); if (value == null) { tm.put(c, 1); } else { value++; tm.put(c, value); } } StringBuilder sb = new StringBuilder(); Set<Character> set1 = tm.keySet(); for (Character ca : set1) { Integer value = tm.get(ca); sb.append(ca).append("(").append(value).append(")"); } String result = sb.toString(); System.out.println("result:" + result); } }
- 子可以往父那里走,但是父不能往子那里走。
- 反转并不是逆序。只有是正序的情况下反转才是逆序。
- 如果同时有自然排序和比较器排序,以比较器排序为主。
- Collectios的常用方法
public static <T> void sort(List<T> list) 排序
B:public static <T> int binarySearch(List<?> list,T key)二分查找
C:public static <T> T max(Collection<?> coll)返回最大值
D:public static void reverse(List<?> list)反转
E:public static void shuffle(List<?> list)任意置换(一般洗牌就用该方法)
- 集合的总结
集合(自己补齐)
Collection(单列集合)
List(有序,可重复)
ArrayList
底层数据结构是数组,查询快,增删慢
线程不安全,效率高
Vector
底层数据结构是数组,查询快,增删慢
线程安全,效率低
LinkedList
底层数据结构是链表,查询慢,增删快
线程不安全,效率高
Set(无序,唯一)
HashSet
底层数据结构是哈希表。
哈希表依赖两个方法:hashCode()和equals()
执行顺序:
首先判断hashCode()值是否相同
是:继续执行equals(),看其返回值
是true:说明元素重复,不添加
是false:就直接添加到集合
否:就直接添加到集合
最终:
自动生成hashCode()和equals()即可
LinkedHashSet
底层数据结构由链表和哈希表组成。
由链表保证元素有序。
由哈希表保证元素唯一。
TreeSet
底层数据结构是红黑树。(是一种自平衡的二叉树)
如何保证元素唯一性呢?
根据比较的返回值是否是0来决定
如何保证元素的排序呢?
两种方式
自然排序(元素具备比较性)
让元素所属的类实现Comparable接口
比较器排序(集合具备比较性)
让集合接收一个Comparator的实现类对象
Map(双列集合)
A:Map集合的数据结构仅仅针对键有效,与值无关。
B:存储的是键值对形式的元素,键唯一,值可重复。
HashMap
底层数据结构是哈希表。线程不安全,效率高
哈希表依赖两个方法:hashCode()和equals()
执行顺序:
首先判断hashCode()值是否相同
是:继续执行equals(),看其返回值
是true:说明元素重复,不添加
是false:就直接添加到集合
否:就直接添加到集合
最终:
自动生成hashCode()和equals()即可
LinkedHashMap
底层数据结构由链表和哈希表组成。
由链表保证元素有序。
由哈希表保证元素唯一。
Hashtable
底层数据结构是哈希表。线程安全,效率低
哈希表依赖两个方法:hashCode()和equals()
执行顺序:
首先判断hashCode()值是否相同
是:继续执行equals(),看其返回值
是true:说明元素重复,不添加
是false:就直接添加到集合
否:就直接添加到集合
最终:
自动生成hashCode()和equals()即可
TreeMap
底层数据结构是红黑树。(是一种自平衡的二叉树)
如何保证元素唯一性呢?
根据比较的返回值是否是0来决定
如何保证元素的排序呢?
两种方式
自然排序(元素具备比较性)
让元素所属的类实现Comparable接口
比较器排序(集合具备比较性)
让集合接收一个Comparator的实现类对象
2:到底使用那种集合(自己补齐)
看需求。
是否是键值对象形式:
是:Map
键是否需要排序:
是:TreeMap
否:HashMap
不知道,就使用HashMap。
否:Collection
元素是否唯一:
是:Set
元素是否需要排序:
是:TreeSet
否:HashSet
不知道,就使用HashSet
否:List
要安全吗:
是:Vector(其实我们也不用它,后面我们讲解了多线程以后,我在给你回顾用谁)
否:ArrayList或者LinkedList
增删多:LinkedList
查询多:ArrayList
不知道,就使用ArrayList
不知道,就使用ArrayList
3:集合的常见方法及遍历方式
Collection:
add() remove() contains() iterator() size()
遍历:
增强for
迭代器
|--List
get()
遍历:
普通for(共三种)
|--Set(就是两种)
Map:
put()
remove()
containskey(),containsValue()
keySet()
get()
value()
entrySet()
size()
遍历:
根据键找值
根据键值对对象分别找键和值
- 模仿斗地主发牌的代码
package cn.itcast_04; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.TreeSet; /* * 思路: * A:创建一个HashMap集合 * B:创建一个ArrayList集合 * C:创建花色数组和点数数组 * D:从0开始往HashMap里面存储编号,并存储对应的牌 * 同时往ArrayList里面存储编号即可。 * E:洗牌(洗的是编号) * F:发牌(发的也是编号,为了保证编号是排序的,就创建TreeSet集合接收) * G:看牌(遍历TreeSet集合,获取编号,到HashMap集合找对应的牌) */ public class PokerDemo { public static void main(String[] args) { // 创建一个HashMap集合 HashMap<Integer, String> hm = new HashMap<Integer, String>(); // 创建一个ArrayList集合 ArrayList<Integer> array = new ArrayList<Integer>(); // 创建花色数组和点数数组 // 定义一个花色数组 String[] colors = { "♠", "♥", "♣", "♦" }; // 定义一个点数数组 String[] numbers = { "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2", }; // 从0开始往HashMap里面存储编号,并存储对应的牌,同时往ArrayList里面存储编号即可。 int index = 0; for (String number : numbers) { for (String color : colors) { String poker = color.concat(number); hm.put(index, poker); array.add(index); index++; } } hm.put(index, "小王"); array.add(index); index++; hm.put(index, "大王"); array.add(index); // 洗牌(洗的是编号) Collections.shuffle(array); // 发牌(发的也是编号,为了保证编号是排序的,就创建TreeSet集合接收) TreeSet<Integer> fengQingYang = new TreeSet<Integer>(); TreeSet<Integer> linQingXia = new TreeSet<Integer>(); TreeSet<Integer> liuYi = new TreeSet<Integer>(); TreeSet<Integer> diPai = new TreeSet<Integer>(); for (int x = 0; x < array.size(); x++) { if (x >= array.size() - 3) { diPai.add(array.get(x)); } else if (x % 3 == 0) { fengQingYang.add(array.get(x)); } else if (x % 3 == 1) { linQingXia.add(array.get(x)); } else if (x % 3 == 2) { liuYi.add(array.get(x)); } } // 看牌(遍历TreeSet集合,获取编号,到HashMap集合找对应的牌) lookPoker("风清扬", fengQingYang, hm); lookPoker("林青霞", linQingXia, hm); lookPoker("刘意", liuYi, hm); lookPoker("底牌", diPai, hm); } // 写看牌的功能 public static void lookPoker(String name, TreeSet<Integer> ts, HashMap<Integer, String> hm) { System.out.print(name + "的牌是:"); for (Integer key : ts) { String value = hm.get(key); System.out.print(value + " "); } System.out.println(); } }
- Map集合的底层数据结构仅仅针对键有效,与值无关。
- Throwable类的两个子类:errror:严重问题,我们不处理。这种问题一旦出现就很严重,比如内存溢出。Exception:1.编译问题:不是runtimexception的异常,是必须要进行处理的,否则编译就不通过。2。运行问题:runtimeexception:这种问题也不处理,因为是你的问题,这个问题的出现时我们得代码肯定不够严谨,是需要重新更正代码的。
- 如果程序出现了问题,我们没有做任何的处理,最终jvm会做出默认的处理。把异常的名称,原因及出现的问题等信息输出到控制台,同时会终止程序,不会继续向下运行。包括try里面本身的。-------->待续