#1、集合可分为Collection和Map
**Collection接口**
A、List接口:存储有序的,可以重复的元素
ArrayList(主要的实现类,底层用数组实现没,线程不安全的)
LinkedList(对于频繁的插入 、删除操作,链表实现的)
Vector(古老的实现类、线程安全的)
B、Set接口:存储无序的不可重复的元素
HashSet、LinkedHashSet、TreeSet
Map接口:存储“键-值”对的数据
HashMap、LinkedHaseMap、TreeMap、Hashtable(子类:Properties)
他们三个类大体方法和使用相同。ArrayList 是线程不安全的,而 Vector 是线程安全的,即使为保证 List 集合线程安全,也不推荐使用Vector。对于频繁的插入或删除元素的操作,建议使用LinkedList类,效率较高, 经常遍历时 ArrayList 效率较高。
ArrayList 采用的是数组形式来保存对象的,这种方式将对象放在连续的位置中,所以最大的缺点就是插入删除时非常麻烦.
LinkedList 采用的将对象存放在独立的空间中,而且在每个空间中还保存下一个链接的索引,但是缺点就是查找非常麻烦,要丛第一个索引开始。
#Collection接口
#Collection接口 – List接口
-
存储对象可以考虑 ①数组 ②集合
-
数组存储的特点:Student[] stu = new Student[20];
-数组存储的弊端 ① 一旦创建,其长度不可变。②真实的数组存放的对象的个数是不可用 -
Collection的方法
①int size()//获取长度
②boolean add(Object obj)//添加元素
③ addAll(Collection coll)//讲形参coll中包含的所有元素添加到当前集合中
④ 查看元素集合
System.out.println(coll)//
⑤ isEmpty()//判断集合是否为空
对象.isEmpty() //值是true false
⑥ clear()清空集合元素
对象.clear();
⑦ contains(Object obj) 判断集合中是否包含指定的obj元素,如果包含 返回true,反之false。
判断的依据,根据元素所在的类的equals()方法进行判断
//明确:如果存入集合中的元素是自定义类的对象,要求:自定义类要重新equals()方法!
对象.contains(“aa”);
⑧ containsAll(Contains coll) 判断当前集合中是否包含coll中所有的元素
coll. containsAll(新集合);//返回 Boolean
⑨ retainAll(Contains coll)//求当前集合与coll的共有的元素,返回给当前集合 coll.retainAll(coll1);//返回两个集合中共有的元素,返回给 coll
⑩ remove(Object obj)//删除集合中的obj元素,若删除成功 返回 true 否则 返回false coll.remover(值)
集合的遍历
11)removeAll
coll. removeAll(coll1);//删除两个集合共有的元素,返回coll剩余的元素
12)equals//返回两个集合是否相等
coll.equals(coll1);//返回Boolean
13)hashCode() //求集合的hash值 set
14)toArray();//将集合返回数组
Objet[] obj = coll.toArray();
- iterator() 获取一个迭代器对象
while(Iterator.hasNext){
System.out.print(集合对象.next());
}
增强for循环
for(Object x:coll){
System.out.print(x);
)
#Collection举例
因为Collection接口无法被实例化;我们测试Collection 接口的所有例子使用ArrayList类帮忙实现
Collection a = new ArrayList();
// 打印长度
System.out.println(a.size());
// 添加元素
a.add(“张三”);
// 添加一个集合的元素
Collection<String> copyA = new ArrayList<String>();
copyA.add("TONY");
copyA.add("李四");
a.addAll(copyA); // 将另一个集合元素添加到 a 集合中
// 判断是否为空
System.out.println("是否为空:" + a.isEmpty());
// 清空集合元素
// copyA.clear(); 为了测试 不真删..... 不然没得玩了...
// 判断集合是否包含指定的obj元素
System.out.println(a.contains("张三"));
// 判断集合是否完全包含另一个集合
System.out.println(a.containsAll(copyA));
// 只留下和另一个集合重复的值
System.out.println(a);
System.out.println(a.retainAll(copyA));
System.out.println(a);
// 删除匹配某一个数据
System.out.println(a.remove("张三") ? "删除成功" : "没删除成功" );
// 删除匹配一个集合的数据
a.removeAll(copyA);
// 返回成数组
Object[] intArr = a.toArray();
// 遍历
System.out.println(copyA);
copyA.add("王伟");
copyA.add("钱学森");
// 使用Iterator接口
Iterator i = copyA.iterator();
while(i.hasNext()){ //是否有下一个
System.out.print(i.next() + " (-) "); // 进行查询
}
// 使用foreach遍历
System.out.println("\n符号纯粹只是为了区别...");
for (Object object : copyA) {
System.out.print(object + " (o) ");
}
}
##Collection接口 - list接口----------ArrayList类定义方法
ArrayList
add(int index,Object ele);在指定的索引位置 index添加元素ele 添加的索引位置不能超过现有集合长度
Object get(int index)//获取指定索引的元素值
Object remove(int index)//删除指定索引的元素 并返回该元素
Object set(int index,Object ele)//设置指定索引位置的元素为ele 返回该位置的原有元素
boolean addAll(int index,Collection eles) //将eles 集合中的所有元素添加到集合中
Int indexOf(Object obj)
Int lastindexOf(Objext obj)
List subList(int fromindex,int toindex)
List常用的方法:增 add(Object obj),删remove
改set(),查get,插 add 长度 size()
语法:List list = new ArrayList
1)添加值list.add(值);
list.add(0,43);//在第一个位置添加
2)获取位置元素的值
Object obj = list.get(下标);
3)删除指定位置的元素
list.remove(0);
4)修改指定位置的元素
list.set(0,432);
5) indexOf返回obj在集合中首次出现的位置,没有返回-1
6)lastindexOf返回obj在集合中最后出现的位置,没有返回-1
list.indexOf(值)//会调用equals方法
list.lastindexOf(值)
7) subList(int fromindex,int toindex)//返回从fromindex到toindex的lsit
list.subList(0,4)//包含左边 不包含右边的新集合
#=ArraysList方法综合举例==================
public static void main(String[] args) {
// 使用List接口 创建一个ArrayList
List<String> student = new ArrayList<String>();
student.add("小明");
student.add("小红");
student.add("小刚");
System.out.println(student);
student.add(2, "林丹"); //将林丹插入第二个位置之前
System.out.println(student);
student.remove(2);// 删除下标为2的
System.out.println(student);
student.set(0, "马龙"); //将下标为0的改为马龙
System.out.println(student);
//创建一个集合
List<String> footballPlayer = new ArrayList<String>();
footballPlayer.add("C罗");
footballPlayer.add("梅西");
footballPlayer.add("贝尔");
student.addAll(footballPlayer); //添加一个集合(足球队)
System.out.println(student);
System.out.println("获取C罗下标: "+ student.indexOf("C罗"));
System.out.println("获取C罗下标: "+ student.lastIndexOf("C罗"));
System.out.println("求字串下标 1-2 " +student.subList(1, 3));
System.out.println("获取梅西: " + student.get(4));
}
==================================================
Collection接口 – List接口 -LinkedList
-
void addFirst(Object obj)
-
void addLast(Object obj)
-
Object getFirst()
-
Object getLast()
-
Object removeFirst()
-
Object removeLast()
=LinkedList综合举例================
public static void main(String[] args) {
// 使用List接口 创建一个LinkedList
LinkedList persons = new LinkedList();
persons.add(“大明”);
persons.add(“大红”);
persons.add(“大刚”);
System.out.println(persons);// 添加到集合首位 persons.addFirst("葫芦娃大娃"); // 添加到集合末尾 persons.addLast("葫芦娃七娃"); System.out.println(persons); System.out.println("抓第一个: " + persons.getFirst()); System.out.println("抓最后一个: " + persons.getLast()); System.out.println("带走第一个: " + persons.removeFirst()); System.out.println("带最后一个: " + persons.removeLast()); System.out.println(persons);
}
List常用子类还包括 Vector
他们三个类大体方法和使用相同。**ArrayList 是线程不安全的,而 Vector 是线程安全的,即使为保证 List 集合线程安全,也不推荐使用Vector**。**对于频繁的插入或删除元素的操作,建议使用LinkedList类,效率较高, 经常遍历时 ArrayList 效率较高。**
ArrayList 采用的是数组形式来保存对象的,这种方式将对象放在连续的位置中,所以最大的缺点就是插入删除时非常麻烦.
LinkedList 采用的将对象存放在独立的空间中,而且在每个空间中还保存下一个链接的索引,但是缺点就是查找非常麻烦,要丛第一个索引开始。
泛型:
1.解决元素存储的安全性问题
2.解决获取数据元素时,需要类型强转的问题
语法:List list =new ArrayList;//E表示数据类型
Collection接口 – Set接口
Set接口是Collection的子接口,Set接口没有提供额外的方法
Set 集合不允许包含相同的元素,如果试把两个相同的元素加入同一个 Set 集合中,则添加操作失败。
Set 判断两个对象是否相同不是使用 == 运算符,而是根据 equals 方法
##Collection接口 – Set接口 - HashSet 类**
HashSet类实现了Set接口,由哈希表支持.它不保证Set的迭代顺序,特别是它不保证该顺序恒久不变.
HashSet 是 Set 接口的典型实现,大多数时候使用 Set 集合时都使用这个实现类。HashSet 按 Hash 算法来存储集合中的元素,因此具有很好的存取和查找性能。
HashSet 具有以下特点:
不能保证元素的排列顺序
元素不能重复(equals方法判断重复)
HashSet 不是线程安全的
集合元素可以是 null
因为无法保证顺序HashSet无法获取到某一项的值 只能遍历
- add
- clear
- contains
- remove
- size
public static void main(String[] args) {
Set s = new HashSet();
s.add(“A”);
s.add(“B”);
s.add(“C”);
s.add(“D”);
s.add(“E”);
s.add(“E”);
System.out.println(s);
s.remove("E");// 删除值为E的集合项
System.out.println(s);
System.out.println("是否包含C: " + s.contains("C"));
System.out.println("SET长度 " + s.size());
}
##LinkedHashSet 是Hashset的子类
LinkedHashSet集合同样是根据元素的hashCode值来决定元素的存储位置,但是它同时使用链表维护元素的次序。这样使得元素看起 来像是以插入顺序保存的,也就是说,当遍历该集合时候,LinkedHashSet将会以元素的添加顺序访问集合的元素。
LinkedHashSet在迭代访问Set中的全部元素时,性能比HashSet好,但是插入时性能稍微逊色于HashSet。
PS:链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。
**Collection接口 – Set接口 - TreeSet类**
TreeSet 是 SortedSet 接口的实现类,TreeSet 可以确保集合元素处于排序状态。
Comparator comparator()
Object first()
Object last()
Object lower(Object e)
Object higher(Object e)
SortedSet subSet(fromElement, toElement)
SortedSet headSet(toElement)
SortedSet tailSet(fromElement)
TreeSet s = new TreeSet();
s.add(“z”);
s.add(“a”);
s.add(“c”);
s.add(“g”);
System.out.println(s);
System.out.println("第一个元素: " + s.first());
System.out.println("最后一个元素: " + s.last());
System.out.println("低一点 " + s.lower("g"));
System.out.println("高一点 " + s.higher("g"));
SortedSet ss = s.subSet("a", "g");
System.out.println("求子集 " + ss);
System.out.println("求子集 " + s.headSet("g"));
System.out.println("求子集 " + s.tailSet("g"));
大家都知道treeset是可以排序的, 字母和数字等内容还好, 排序跟着字典顺序走就是了, 那么问题来了, 如果存入的是一个学生对象… 那如何排序??
TreeSet 会调用集合元素的 compareTo(Object obj) 方法来比较元素之间的大小关系,然后将集合元素按升序排列. 如果试图把一个对象添加到 TreeSet 时,则该对象的类必须实现 Comparable 接口。
实现 Comparable 的类必须实现 compareTo(Object obj) 方法,两个对象即通过 compareTo(Object obj) 方法的返回值来比较大小。
class Student implements Comparable {
public String name;
public int age;
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public int compareTo(Object o) {
if (!(o instanceof Student)) {
return 0;
}
if (o == this) {
return 1;
}
Student s = (Student) o;
if (this.age < s.age) {
return 1;
}else{
return -1;
}
}
}
public class Test {
public static void main(String[] args) {
Student xiaohong = new Student(“小红”, 10);
Student xiaoming = new Student(“小明”, 12);
Student xiaogang = new Student(“小刚”, 13);
TreeSet s = new TreeSet();
s.add(xiaohong);
s.add(xiaoming);
s.add(xiaogang);
Iterator i = s.iterator();
while(i.hasNext()){
System.out.println(i.next().name);
}
}
}
通过Comparator接口的帮助。需要重写compare(T o1,T o2)方法。
利用int compare(T o1,T o2)方法,比较o1和o2的大小:如果方法返回正整数,则表示o1大于o2;如果返回0,表示相等;返回负整数,表示o1小于o2。
class Student {
String name;
int age;
Student(String name, int age) {
this.name = name;
this.age = age;
}
public String toString() {
return this.name;
}
}
class MyComparator implements Comparator {
@Override
public int compare(Student s1, Student s2) {
return s1.age - s2.age == 0 ? 0 : (s1.age - s2.age > 0) ? -1 : 1;
}
}
public class Test {
public static void main(String[] args) {
TreeSet tree = new TreeSet(new MyComparator());
tree.add(new Student(“小明”, 10));
tree.add(new Student(“小红”, 15));
tree.add(new Student(“小刚”, 9));
tree.add(new Student(“小光”, 93));
System.out.println(tree);
}
}
当需要把一个对象放入 TreeSet 中,重写该对象对应的 equals() 方法时,应保证该方法与 compareTo(Object obj) 方法有一致的结果:如果两个对象通过 equals() 方法比较返回 true,则通过 compareTo(Object obj) 方法比较应返回 0
//手写 判断两个对象相等方法.
public boolean equals(Object o) {
Student s = (Student) o;
return (s.age == age && s.name.equals(name));
}
public int hashCode(){
return age * name.hashCode();
}
// eclipse同时也提供快捷键 ALT + SHIFT + F + H 生成 equals和hashCode方法重写.
#Map接口
Map:保存多个映射关系的对象
Map与Collection并列存在。用于保存具有映射关系的数据:Key-Value(键值对)
Map 中的 key 和 value 都可以是任何引用类型的数据
Map 中的 key 用Set来存放,不允许重复,即同一个 Map 对象所对应的类,须重写hashCode()和equals()方法。
常用String类作为Map的“键”。
key 和 value 之间存在单向一对一关系,即通过指定的 key 总能找到唯一的、确定的 value。
常用方法
添加、删除操作:
Object put(Object key,Object value)
Object remove(Object key)
void putAll(Map t)
void clear()
元视图操作的方法:
Set keySet()
Collection values()
Set<Map.Entry<K, V>> entrySet();–返回键值对象的集合
元素查询的操作:
Object get(Object key)
boolean containsKey(Object key)
boolean containsValue(Object value)
int size()
boolean isEmpty()
boolean equals(Object obj)
=Map 综合举例====================
public static void main(String[] args) {
Map<String, String> map = new HashMap<String, String>();
map.put(“s01”, “小王”);
map.put(“s02”, “小李”);// 没有小李
map.put(“s02”, “小虎”);
map.put(“s03”, “小杰”);
map.put(“s04”, “小王”);
System.out.println("获取 s02 的值: " + map.get("s02"));
map.put("s05", "小强"); //
map.remove("s05"); // 删除
Set<String> set = map.keySet(); // 将所有Map的key传递给Set
Iterator<String> it = set.iterator();
System.out.println("===Key集合的集合===");
while (it.hasNext()) {
System.out.println(it.next());
}
Collection<String> coll = map.values();
it = coll.iterator();
System.out.println("===Value集合===");
while (it.hasNext()) {
System.out.println(it.next());
}
System.out.println("是不是空的? " + map.isEmpty());
System.out.println("清空集合");
map.clear();
System.out.println("是不是空的? " + map.isEmpty());
System.out.println("有没有 s04 的key ? " + map.containsKey("s04"));
System.out.println("有没有 小王 的key ? " + map.containsValue("小杰"));
}
==================================================
##HashMap
*Map接口的常用实现类:HashMap、TreeMap和Hashtable、Properties。
*
HashMap是 Map 接口使用频率最高的实现类。
允许使用null键和null值,与HashSet一样,不保证映射的顺序。
HashMap 判断两个 key 相等的标准是:两个 key 通过 equals() 方法返回 true,hashCode 值也相等。
HashMap 判断两个 value相等的标准是:两个 value 通过 equals() 方法返回 true。
###LinkedHashMap
LinkedHashMap 是 HashMap 的子类
与LinkedHashSet类似,LinkedHashMap 可以维护 Map 的迭代顺序:迭代顺序与 Key-Value 对的插入顺序一致
Map<String, String> map = new LinkedHashMap<String, String>();
map.put("s01", "小王");
map.put("s02", "小李");// 没有小李
System.out.println(map);
HashTable
Hashtable与HashMap的用法基本一致,但是也存在一些区别:
1)HashMap可以允许存在一个为null的key和任意个为null的value,但是HashTable中的key和value都不允许为null。
2)Hashtable是线程安全的,而HashMap是线程不安全的。
Properties
Properties(Java.util.Properties),主要用于读取Java的配置文件,在Java中,其配置文件常为.properties文件,格式为文本文件,文件的内容的格式是“键=值”的格式,文本注释信息可以用"#"来注释。
它提供了几个主要的方法:
1. load ( InputStream inStream),从输入流中读取属性列表(键和元素对)。通过对指定的文件(比如说上面的 test.properties 文件)进行装载来获取该文件中的所有键 - 值对。以供 getProperty ( String key) 来搜索。
2. getProperty ( String key),用指定的键在此属性列表中搜索属性。也就是通过参数 key ,得到 key 所对应的 value。
3. setProperty ( String key, String value) ,调用 Hashtable 的方法 put 。他通过调用基类的put方法来设置 键 - 值对。
4. store ( OutputStream out, String comments),以适合使用 load 方法加载到 Properties 表中的格式,将此 Properties 表中的属性列表(键和元素对)写入输出流。与 load 方法相反,该方法将键 - 值对写入到指定的文件中去。
5. clear (),清除所有装载的 键 - 值对。该方法在基类中提供。
##TreeMap
TreeMap存储 Key-Value 对时,需要根据 key-value 对进行排序。TreeMap 可以保证所有的 Key-Value 对处于有序状态。
TreeMap 的 Key 的排序:
自然排序:TreeMap 的所有的 Key 必须实现 Comparable 接口,而且所有的 Key 应该是同一个类的对象,否则将会抛出 ClasssCastException
定制排序:创建 TreeMap 时,传入一个 Comparator 对象,该对象负责对 TreeMap 中的所有 key 进行排序。此时不需要 Map 的 Key 实现 Comparable 接口
TreeMap判断两个key相等的标准:两个key通过compareTo()方法或者compare()方法返回0。
若使用自定义类作为TreeMap的key,所属类需要重写equals()和hashCode()方法,且equals()方法返回true时,compareTo()方法应返回0。
内部比较器:在需要比较排序的类中 实现comparable接口,并且实现compareTo方法
外部比较器:单独定义一个类,实现comparator接口,并实现compare方法,在创建TreeMap实例对象时,作为构造器参数传入,从而制定TreeMap的排序规则
**//Tree 可以排序 但是不能以值排序 只能以key进行排序 这点比较特殊**
class Student {
public int age;
public String name;
public Student(int age, String name) {
super();
this.age = age;
this.name = name;
}
@Override
public String toString() {
return "Student [age=" + age + ", name=" + name + "]";
}
}
class StuAgeComparator implements Comparator {
public int compare(Student s1, Student s2) {
if (s1.age > s2.age) {
return -1;
} else {
if (s1.age == s2.age) {
return 0;
}
return 1;
}
}
}
public class Test {
public static void main(String[] args) {
Map<Student, String> map = new TreeMap<Student, String>(
new StuAgeComparator());
map.put(new Student(25, “宇智波鼬”), “s001”);
map.put(new Student(18, “佐助”), “s002”);
map.put(new Student(20, “李洛克”), “s003”);
map.put(new Student(19, “鸣人”), “s004”);
map.put(new Student(40, “四代火影”), “s005”);
map.put(new Student(65, “三代火影”), “s006”);
System.out.println("遍历Map集合");
Set<Student> set = map.keySet();
Iterator<Student> it = set.iterator();
while (it.hasNext()) {
Student key = it.next();
String value = map.get(key);
System.out.println(key + " : " + value.toString());
}
}
}
操作集合的工具类:Collections
Collections 是一个操作 Set、List 和 Map 等集合的工具类
Collections 中提供了一系列静态的方法对集合元素进行排序、查询和修改等操作,还提供了对集合对象设置不可变、对集合对象实现同步控制等方法
排序操作:(均为static方法)
reverse(List):反转 List 中元素的顺序
shuffle(List):对 List 集合元素进行随机排序
sort(List):根据元素的自然顺序对指定 List 集合元素按升序排序
sort(List,Comparator):根据指定的 Comparator 产生的顺序对 List 集合元素进行排序
swap(List,int, int):将指定 list 集合中的 i 处元素和 j 处元素进行交换
查找、替换
Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素
Object max(Collection,Comparator):根据 Comparator 指定的顺序,返回给定集合中的最大元素
Object min(Collection)
Object min(Collection,Comparator)
int frequency(Collection,Object):返回指定集合中指定元素的出现次数
void copy(List dest,List src):将src中的内容复制到dest中
boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替换 List 对象的所有旧值
public static void main(String[] args) {
LinkedList persons = new LinkedList();
persons.add(“tony”);
persons.add(“andy”);
persons.add(“mark”);
persons.add(“mark”);
persons.add(“zero”);
System.out.println("原本" + persons);
Collections.reverse(persons);
System.out.println("翻转后" + persons);
Collections.shuffle(persons);
System.out.println("随机后" + persons);
Collections.sort(persons);
System.out.println("升序" + persons);
Collections.swap(persons, 0, 3);
System.out.println("0 和 3交换后" + persons);
System.out.println("求最大" + Collections.max(persons));
System.out.println("求最小" + Collections.min(persons));
System.out.println("求最小" + Collections.min(persons));
System.out.println("计算mark出现次数"
+ Collections.frequency(persons, "mark"));
LinkedList<String> personsCopy = new LinkedList<String>();
Collections.replaceAll(persons, "mark", "happy new year"); //替换所有mark
System.out.println("当前" + persons);
}
##* 什么是hash表
HASH表主要就是提供更快的查找速度,由hash值和数值组成,简单来说就是分桶。
比如说你们学校的一个年级有很多班是吧?
那么现在要查找一位同学。如果不看班级直接找,就需要每个班级一个一个的查找是不?那现在因为分了班级,我们有一个函数可以通过名字产生它的班级号。比如说何磊,二班。
那么现在我们直接hash(何磊) = 2;
然后我们就直接从2班开始找。
如果2班有50个学生,那么我们最多查找50次对吗?
好。假设你们年级一共有100个班,如果没有这个hash函数,那么直接找,最坏可能要查找50*100=5000次。!!
这个班级其实就是每个桶!!
这就是分桶。。。通过哈希函数产生哈希值,然后相同哈希值的元素放在相同的桶里边。。。!
这样可以通过hash这个间接作用减少查找的时间和次数!!这就是它的意义!!