Java基础之集合算法与数据结构
集合:存储批量对象,可以看成可变长度的数组。
Collection :单列集合 --List:有序可重复
--ArrayList:底层数据结构为数组,元素连续,增删慢,查找修改快。(数据存放顺序为添加顺序)
--LinkedList:底层数据结构为双向链表,元素可以不连续,增删快,查找修改慢。
遍历:for,for-each,迭代器
单项(向后)Iterator接口:hasNext()、next、remove
双向遍历ListIterator子接口:hasPrevious(指针当前元素前是否含有元素)、previous(返回所指元素前一项,指针上移)、add(添加)、set(替换)
--Set:无序不可重复
--HashSet:底层数据结构为哈希算法 hashCode,equals
--TreeSet:底层数据结构为二叉树,按照自排序
实现Comparable,并实现compareTo方法,根据方法的返回值的结果进行排序。
add,remove,size
<? extends E>: E类型及其子类型
<? super E>: E类型及其父类型
Map:双列集合
存储具有映射关系的一对一对的数据,key---value
key保证唯一,value可重复
--Map:
---HashMap:key是按照哈希算法存储 hashCode equals
---TreeMap:key是按照二叉树存储的,key需要进行自然顺序排序 实现Comparable接口,实现CompareTo方法
Java.Map的三种遍历方法
package com.collection; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; /** * 集合的一个很重要的操作---遍历,学习了三种遍历方法,三种方法各有优缺点 * @author chengjie */ public class TestMap { /** * 最常规的一种遍历方法,最常规就是最常用的,虽然不复杂但很重要,最熟悉的 * values 返回包含映射内所有值得集合 */ public static void work(Map<String, Student> map) { Collection<Student> c = map.values(); Iterator it = c.iterator(); for (; it.hasNext();) { System.out.println(it.next()); } } /** * 利用keyset进行遍历,它的优点在于可以根据你所想要的key值得到你想要的 values,更具灵活性 * keySet 返回映射所有键的集合 */ public static void workByKeySet(Map<String, Student> map) { Set<String> key = map.keySet(); for (Iterator it = key.iterator(); it.hasNext();) { String s = (String) it.next(); System.out.println(map.get(s)); } } /** * 比较复杂的一种遍历在这里,呵呵~~他很暴力哦,它的灵活性太强了,想得到什么就能得到什么 * entrySet 返回包含所有键值对的集合 */ public static void workByEntry(Map<String, Student> map) { Set<Map.Entry<String, Student>> set = map.entrySet(); for (Iterator<Map.Entry<String, Student>> it = set.iterator(); it.hasNext();) { Map.Entry<String, Student> entry = (Map.Entry<String, Student>) it.next(); System.out.println(entry.getKey() + "--->" + entry.getValue()); } } public static void main(String[] args) { Map<String, Student> map = new HashMap<String, Student>(); Student s1 = new Student("宋江", "1001", 38); Student s2 = new Student("卢俊义", "1002", 35); Student s3 = new Student("吴用", "1003", 34); map.put("1001", s1); map.put("1002", s2); map.put("1003", s3); Map<String, Student> subMap = new HashMap<String, Student>(); subMap.put("1008", new Student("tom", "1008", 12)); subMap.put("1009", new Student("jerry", "1009", 10)); map.putAll(subMap); work(map); workByKeySet(map); workByEntry(map); } } class Student { private String name; private String id; private int age; public Student(String name, String id, int age) { this.name = name; this.id = id; this.age = age; } @Override public String toString() { return "Student{" + "name=" + name + "id=" + id + "age=" + age + '}'; } }
Set集合数据结构
TreeSet:底层数据结构为:二叉树,将元素按照自然顺序顺序存放。
存储自定义对象时,必须实现Comparable接口,并实现该接口的compareTo方法
根据该方法的返回值进行自然顺序排序,
返回值为正整数,负整数,0,如果是0意味着是相同元素。
HashSet:底层数据结构为:哈希算法。
每个要存储的对象都会先计算哈希码值(hashCode方法),如果哈希值不同则存入到集合中;如果哈希值相同,会通过equals方法进行第二次校验,比较是否是相同对象。
package com.collection; import java.util.TreeSet; public class TreeSetDemo { public static void main(String[] args) { TreeSet<Teacher> set = new TreeSet<Teacher>(); set.add(new Teacher("lisi01", 18)); set.add(new Teacher("lisi11", 22)); set.add(new Teacher("lisi21", 19)); set.add(new Teacher("lisi05", 19)); System.out.println(set); } } class Teacher implements Comparable<Teacher>{ private String name; private int age; public Teacher(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return name+"...."+age; } public int compareTo(Teacher o) { int num = this.age - o.age; if(num == 0) return this.name.compareTo(o.name) ; return num; } }
HashSet哈希算法实现原理剖析:
任何对象均有自己的哈希值,该值通过调用对象的hashCode()方法(继承自Object类)获得。
Object类:是所有对象的直接或者是间接根类;boolean equals(Object obj):比较两个对象是否相同;int hashCode():返回的是对象的内在散列码值(哈希值)
注意:哈希值相同不能说明是对象相同,对象相同那么哈希值一定相同。
package com.collection; /** * 自定义类对其对象等同性比较时自行实现equals方法 * @author chengjie * */ public class MyDate { private int day; private int month; private int year; public MyDate(int day, int month, int year) { this.day = day; this.month = month; this.year = year; } @Override public boolean equals(Object obj) { boolean result = false; if ((obj != null) && (obj instanceof MyDate)) { MyDate d = (MyDate) obj; if ((day == d.day) && (month == d.month) && (year == d.year)) { result = true; } } return result; // if (this == obj) // return true; // if (obj == null) // return false; // if (getClass() != obj.getClass()) // return false; // MyDate other = (MyDate) obj; // if (day != other.day) // return false; // if (month != other.month) // return false; // if (year != other.year) // return false; // return true; } /** date属性按位异或,保证相等的MyDate对象具有相同的散列码值,不同日期返回不同的值 */ @Override public int hashCode() { return (day << 4 ^ month ^ year); } }
当向HashSet集合中添加元素时:
import java.util.Arrays; public class HashSetDemo { public static Phone[] phones=new Phone[9]; public static void main(String[] args) { Phone p1=new Phone("apple", "iphone7", 32, 128); Phone p2=new Phone("apple", "iphone7", 32, 128); Phone p3=new Phone("apple", "iphone7", 64, 128); Phone p4=new Phone("apple", "iphone7", 64, 64); Phone[] array={p1,p2,p3,p4}; for(Phone p:array){ add(p); } } public static void add(Phone p){ System.out.println("-----------------添加1个元素--------------------"); int hashCode=p.hashCode(); System.out.println("调取p的hashCode方法,得到的值是:"+hashCode); int index=hashCode%phones.length; System.out.println("用hashCode对数组长度取余,得到下标:"+index); boolean flag=phones[index]==null?true:false; System.out.println("判断数组对应位置是否有元素:"+(flag?"没有元素":"有元素")); if(flag){//没有元素 System.out.println("直接执行添加操作"); phones[index]=p; System.out.println("添加完成"); }else{//有元素 boolean flag2=phones[index].equals(p); System.out.println("调用equals方法,返回值为:"+flag2); if(flag2){ System.out.println("两个元素相等,说明重复,不再添加"); }else{ System.out.println("两个元素不等,扩大数组长度,重新尝试添加"); phones=Arrays.copyOf(phones, phones.length*2); } } System.out.println("-----------------完成1次方法调用--------------------"); } }

浙公网安备 33010602011771号