根据数据的不同,Java的集合分为2大体系:
List :按照插入顺序保存数据,数据可以重复的
具体的实现类: ArrayList, LinkedList
Set : 集,无序保存,数据不能重复
具体的实现类 HashSet
Queue : 队列
具体的实现类:ArrayBlockingQueue
具体的实现 : HashMap, Hashtable
创建第一个集合对象:ArrayList
ArrayList list = new ArrayList(3);
- 不需要传递构造参数,直接new就可以,底层数组为空数组
- 构造参数需要传递一个int类型的值,用于设定底层数组的长度
- 构造参数需要传递一个Collection集合类型的值,用于将其他集合中的数据放置在当前集合中
// add方法可以增加数据,只要将数据作为参数传递到add方法即可
// 添加数据时,如果集合中没有任何的数据,那么底层会创建长度为10的数组
list.add("zhangsan");
list.add("zhangsan");
list.add("wangwu");
list.add("zhaoliu");
// 获取集合中数据的条数
System.out.println(list.size());
// 获取指定位置的数据,可以采用索引的方式
System.out.println(list.get(1));
// 遍历集合中的数据
for ( int i = 0; i < list.size(); i++ ) {
//System.out.println("集合中的数据:" + list.get(i));
}
// TODO 如果循环遍历集合数据时,不关心数据的位置,那么可以采用特殊的for循环
// for (循环对象:集合) {}
for ( Object obj : list ) {
System.out.println("集合中的数据:" + obj);
}
// add方法可以传递2个参数的,第一个参数表示数据增加的位置(索引),第二个参数表示数据
list.add(1, "zhaoliu");
addAll()方法
ArrayList list = new ArrayList();
list.add("zhangsan");
list.add("lisi");
list.add("wangwu");
list.add("zhangsan");
list.add("zhangsan");
ArrayList otherList = new ArrayList();
otherList.add("1");
otherList.add("2");
otherList.add("3");
list.addAll( otherList );//将otherList 集合追加到list集合末尾
Object oldVal = list.set(1, "lisi");
System.out.println("修改前的值:" + oldVal);
Object removeVal = list.remove(1);
System.out.println("删除的值:" + removeVal);
// TODO 打印集合对象
System.out.println(list);
// size方法表示集合内部数据的数量
System.out.println(list.size());
// 清空集合中的数据
list.clear();
// 删除指定集合中的数据
list.removeAll(otherList); //删除list集合中otherList集合里的数据
// 判断集合中的数据是否为空
System.out.println(list.isEmpty());
// 用于判断集合中是否存在某条数据,返回布尔类型的值
System.out.println(list.contains("zhangsan123"));
// 用于获取数据在索引中的第一个位置,如果数据不存在,那么返回-1
System.out.println(list.indexOf("zhangsan123"));
System.out.println(list.indexOf("zhangsan"));
System.out.println(list.lastIndexOf("zhangsan"));
//集合变数组
Object[] objects = list.toArray();
// 复制新集合
Object clone = list.clone();
ArrayList list1 = (ArrayList)clone;
System.out.println(list);
System.out.println(list1);
LinkedList list = new LinkedList();
//添加数据
// 增加第一个数据
list.add("zhangsan");
list.add("lisi");
list.add("wangwu");
//向指定的位置添加数据
list.addFirst("lisi"); //增加到数据的前面
list.addLast("2");//增加到数据的后面(默认)
list.add(1, "wangwu"); //添加到第一个位置(0和1之间)
//向集合中添加另一个集合
LinkedList list1 = new LinkedList();
list1.add("zhangsan1");
list1.add("lisi2");
list1.add("wangwu3");
list.addAll(list1); //将list1集合追加到list集合末尾
System.out.println(list.getFirst());
System.out.println(list.getLast());
// 获取数据(遍历数据)
System.out.println(list.get(1));
for ( int i = 0; i < list.size(); i++ ) {
System.out.println(list.get(i));
}
for ( Object obj : list ) {
System.out.println(obj);
}
list.set(1, "zhaoliu");
list.remove("zhangsan");
list.removeFirst(); // 删除第一个
list.removeLast(); // 删除最后一个
list.remove(1);// 删除指定索引
System.out.println(list.size());
System.out.println(list.isEmpty());
list.clear();
list.contains("1");
list.element(); // 获取集合第一个数据
list.indexOf("");
list.lastIndexOf("");
list.push("aaa"); // 添加数据到第一个
System.out.println(list.pop()); // 弹出第一个数据
public class Main{
public static void main(String[] args) {
Person6 person = new Person6();
User6 user = new User6();
ArrayList list = new ArrayList();
list.add(person);
list.add(user);
list.remove(0);
// 从集合中获取的对象类型为Object
Object o = list.get(0);
// 如果想要执行对象的方法,那么需要进行强制类型转换
if ( o instanceof Person6 ) {
Person6 p = (Person6)o;
p.testPerson();
}
}
}
class Person6 {
public void testPerson() {
System.out.println("person...");
}
}
class User6 {
public void testUser() {
System.out.println("user...");
}
}
因为多态语法对对象的使用场景进行了约束,从集合中获取的对象类型为Object,不能直接调用对象类型本身的方法,可见集合对象在处理不同类型的数据时比较繁琐。
集合中没有约定存储数据的类型,不同类型的数据都可以存放在里面,保存了不同类型的数据后,处理起来机会比较麻烦。
泛型和类型
public class Java07_Collection_Generic {
public static void main(String[] args) {
// 泛型语法
// TODO 泛型和类型的区别
// 有时,也把泛型称之为类型参数
MyContainer<User7> myContainer = new MyContainer();
//myContainer.data = new Object();
// 类型存在多态的使用方式,但是泛型没有多态的概念
test(myContainer);
}
public static void test(MyContainer<User7> myContainer) {
System.out.println(myContainer);
}
}
// TODO 容器类
class MyContainer<T> {
public T data;
}
class User7 {
}
// HashSet : Hash + Set
// Hash : 哈希算法,散列算法
HashSet set = new HashSet();
// TODo 增加数据
set.add("zhangsan");
set.add("zhangsan");
set.add("lisi");
set.add("wangwu"); //[zhangsan,lisi,wangwu]
不能修改数据 ,要修改只能先删除再增加。
//删除数据
set.remove("wangwu");
// TODo 查询数据
for (Object o : set) {
System.out.println(o);
}
System.out.println(set);
}
HashSet set = new HashSet();
ArrayList list = new ArrayList();
list.add("zhangsan");
list.add("lisi");
list.add("wamngwu");
set.addAll(list);
Object[] objects = set.toArray();
System.out.println(set.isEmpty());
set.clear();
set.contains("zhangsan");
System.out.println(set.size());
Object clone = set.clone();
System.out.println(clone);
System.out.println(set);
public class Java09_Collection_Set_2 {
public static void main(String[] args) {
HashSet set = new HashSet();
User9 user1 = new User9();
user1.id = 1001;
user1.name = "zhangsan";
System.out.println(user1.hashCode());
User9 user2 = new User9();
user2.id = 1001;
user2.name = "zhangsan";
System.out.println(user2.hashCode());
User9 user3 = new User9();
user3.id = 1002;
user3.name = "lisi";
set.add(user1);
set.add(user2);
set.add(user3);
System.out.println(set);
}
}
class User9 {
public int id;
public String name;
@Override
public String toString() {
return "User["+id+", "+name+"]";
}
}
传递给HashSet一个对象时,进行定位操作的方式:传递一个对象时,以对象的hashCode来做哈希运算,找到数据存放的位置。如果这个位置没有存放数据,则直接将数据存储,如果这个位置已经有数据,则通过equals()方法判断两个数据是否相等,如果相等,则直接丢弃即将要存入的数据;如果不相等,则通过链表将两个位置相同的数据连接起来进行存放(HashSet 底层数据结构为 数组 + 链表)。
如果要使HashSet以对象的属性值是否相同为标准,判断存入的两个对象是否相同,则需要将判断对象是否相等以及获取对象hashCode值的方法进行重写。
public class Java09_Collection_Set_2 {
public static void main(String[] args) {
// TODO 集合 - Collection - Set
// HashSet 底层数据结构为 数组 + 链表
HashSet set = new HashSet();
User9 user1 = new User9();
user1.id = 1001;
user1.name = "zhangsan";
System.out.println(user1.hashCode());
User9 user2 = new User9();
user2.id = 1001;
user2.name = "zhangsan";
System.out.println(user2.hashCode());
User9 user3 = new User9();
user3.id = 1002;
user3.name = "lisi";
set.add(user1);
set.add(user2);
set.add(user3);
System.out.println(set);
}
}
class User9 {
public int id;
public String name;
@Override
// 类似于内存地址
public int hashCode() {
return id;
}
@Override
// 判断两个对象的属性是否完全相同
public boolean equals(Object obj) {
if ( obj instanceof User9 ) {
User9 otherUser = (User9)obj;
if ( otherUser.id == this.id ) {
if ( otherUser.name.equals(this.name) ) {
return true;
}
}
return false;
} else {
return false;
}
}
@Override
public String toString() {
return "User["+id+", "+name+"]";
}
}
如此,两个对象id值相同时,其hashCode值相同,进行哈希定位时其位置也相同;再根据重写的equals方法,可判断出两个对象属性完全相同,即两个数据为同一个值。因此上面的HashSet中只会存储两个对象。
// ArrayBlockingQueue : Array + Blocking(阻塞,堵住) + Queue
ArrayBlockingQueue queue = new ArrayBlockingQueue(3);
// add方法如果增加数据增加不了,直接发生错误。
queue.add("zhangsan");
queue.add("lisi");
queue.add("wangwu");
queue.add("zhaoliu"); // 发生错误,Queue full
queue.put("zhangsan");
System.out.println("第一个人挂号");
queue.put("lisi");
System.out.println("第二个人挂号");
queue.put("wangwu");
System.out.println("第三个人挂号");
queue.put("zhaoliu"); // 不发生错误,但一直阻塞
System.out.println("第四个人挂号");
boolean zhangsan = queue.offer("zhangsan");
System.out.println(zhangsan); // true
boolean lisi = queue.offer("lisi");
System.out.println(lisi);
boolean wangwu = queue.offer("wangwu");
System.out.println(wangwu);
boolean zhaoliu = queue.offer("zhaoliu");
System.out.println(zhaoliu); // false
System.out.println(queue.poll()); // zhangsan
//当队列中没有数据时,执行此方法会输出null
System.out.println(queue.take());// zhangsan
//当队列中没有数据时,执行此方法会阻塞程序
// HashMap : Hash + Map
// 数据存储是无序
HashMap map = new HashMap();
// 添加数据:put
// 修改数据,put方法也可以修改数据,返回值就是被修改的值
map.put("zhangsan", "1");
System.out.println(map.put("zhangsan", "4")); //key相同,value会被覆盖 输出覆盖的值 1
map.put("lisi", "2");
map.put("wangwu", "3");
// 修改数据 返回值就是被修改的值 如果不存在则返回null,且不会在map中添加
Object b = map.replace("b", "4");
System.out.println(b);
//查询数据
System.out.println(map.get("zhangsan"));
// 删除数据
map.remove("zhangsan");
System.out.println(map);
map.remove("zhangsan", "1"); //删除键值对 key value都相同时才删除
// TODO 获取map集合中所有的key
Set set = map.keySet();
for (Object k : set) {
System.out.println(map.get(k)); //获取key对应的value
}
System.out.println(map.containsKey("zhangsan"));
Collection values = map.values();
map.containsValue("1");
System.out.println(map);
HashMap<String, String> map = new HashMap();
// TODO 获取键值对对象
Set<Map.Entry<String, String>> entries = map.entrySet();
for (Map.Entry<String, String> entry : entries) {
System.out.println(entry.getKey() + "=" + entry.getValue()); //lisi=2
}
HashMap与Hashtable
- 实现方式不一样的 : 继承父类不一样
- 底层结构的容量不同: HashMap(16), Hashtable(11)
- HashMap的K,V都可以为null, Hashtable的K, V不能是null
- HashMap的数据定位采用的是Hash算法,但是Hashtable采用的就是hashcode
- HashMap的性能较高,但是Hashtable较低
HashMap<String, Integer> map = new HashMap<String, Integer>();
map.put("a", 1);
map.put("b", 2);
map.put("c", 3);
Set<String> keys = map.keySet();
for (String key : keys) {
if ( "b".equals(key) ) {
map.remove("b");
}
System.out.println(map.get(key));
}
在遍历的时候修改会发生错误ConcurrentModificationException
// TODO 迭代器
Iterator<String> iterator = keys.iterator();
// hasNext方法用于判断是否存在下一条数据
while (iterator.hasNext()) {
// 获取下一条数据
String key = iterator.next();
if("b".equals(key)) {
// remove方法只能对当前数据删除
iterator.remove();
}
System.out.println(map.get(key));
}