集合+泛型
前言
近来在学习算法,刚入门算法,属实是有点吃力,一个力扣的简单题目做一个多小时,悔当初没有好好学算法,当初以为只要学好一门语言和框架就可以了,但是后来发现算法是灵魂,算法不精通那不管学什么也都是捉襟见肘啊。但java这方面的知识也不能落下呀,最近打算开发一个汇总Java SE的项目,于是先来博客把那些重点的知识再串一下吧,今天先从集合+泛型开始,集合那可是相当重要啊!话不多说,整起~
Collection接口
Java集合框架的根是两个接口:Collection和Map,根据Collection和Map的架构,Java中的集合可以分为3类:List是有序集合,他会记录每次添加元素的顺序,元素可以重复;Set是无序集合,不记录元素添加的顺序,元素不可以重复;Map是键值对的集合,每个元素都有键Key和值value对应组成,键值和取值分别存储,键值是无序集合Set,取值是有序集合List。
collenction是单列集合最顶级的接口
注:新建对象的时候可以用new 对象名().var,回车,即可。
迭代器是Collection集合通用的取出数据的方式。
Collection<String> c = new ArrarList<>();
c.add("吴哥"); c.add("海哥");
Iterator it = c.iterator();
while(it.hasNext()){
String n = (String)it.next();
System.out.println(n);
}
Arraylist集合操作
package cn.gather;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class collection {
/**
*创建一个AeeayList集合,用到了多态的概念,
* 泛型是String
* 分别使用while迭代器遍历集合和增强for循环遍历集合
*/
public static void main(String[] args ){
Collection<String> c = new ArrayList<>();
c.add("王虎");//添加数据
c.add("刘华");
c.add("黄花");
System.out.println(c.size());//返回集合的个数
System.out.println(c.isEmpty());//判断集合是否为空
System.out.println(c.contains("刘华"));//判断集合是否包含"刘华"
System.out.println(c.remove("刘华"));//删除刘华
System.out.println(c.size());
Iterator<String> is = c.iterator();//调用接口的实现类
while (is.hasNext()){
//判断集合中有无数据
String em = is.next();//将数据取出,并移到下一个数据上
System.out.println(em);
}
c.clear();//清除集合数据,但不是删除集合
System.out.println(c);
test01();//调用方法
test02();
}
private static void test02(){
ArrayList<String> em = new ArrayList<>();
em.add("花花");
em.add("呼呼");
em.add("黄乎乎");
for (String i:em) {
System.out.println(i);
}
}
private static void test01(){
int[] arr = {
1,2,3,4,5};//建立int数组
for (int i : arr) {
//for增强循环
System.out.print(" "+i);
}
System.out.println();
}
}
集合实例–斗地主
代码如下:
package cn.gather;
import java.util.ArrayList;
import java.util.Collections;
/**
* 斗地主案例
* 1.准备牌
* 2.洗牌
* 3.发牌
* 4.看牌
*/
public class DouDiZhu {
public static void main(String[] args ){
/**
* 1.准备牌
*/
//定义一个可以存储54张牌的ArrayList的集合,集合泛型是String
ArrayList<String> poker = new ArrayList<>();
//定义两个数组。一个存储花色,一个存储数字
String[] colors ={
"♥","♠","♣","♦"};
String[] numbers = {
"2","A","K","Q","J","10","9","8","7","6","5","4","3"};
//先将两个大王和小王存储到集合poker当中
poker.add("大王");
poker.add("小王");
//将花色数组和数字数组组合成52张牌
for (String color:colors) {
for (String number:numbers) {
poker.add(color+number);
}
}
//System.out.println(poker);
/**
* 2.洗牌
* 使用集合工具类Collection中的方法
* static void shuffle(list<?> list)使用默认的方法进行乱序存放
*/
Collections.shuffle(poker);
//System.out.println(poker);
/**
* 3.发牌
*/
//定义四个集合,分别是存放三个人的牌和底牌
ArrayList<String> player01 = new ArrayList<>();
ArrayList<String> player02 = new ArrayList<>();
ArrayList<String> player03 = new ArrayList<>();
ArrayList<String> dipai = new ArrayList<>();
/**
* 遍历集合获取每一张牌
* 然后根据i模除3等于多少发到对应人的手里
* 如果i>=51,则把最后三张发给底牌,因为是从0开始的所以是51而不是52,一共是到53
*/
for (int i = 0; i < poker.size(); i++) {
String s = poker.get(i);
if (i>=51){
dipai.add(s);
}else if (i%3==0){
player01.add(s);
}else if (i%3==1){
player02.add(s);
}else if (i%3==2){
player03.add(s);
}
}
/**
* 4.看牌
*/
System.out.println(player01);
System.out.println(player02);
System.out.println(player03);
System.out.println(dipai);
}
}
数组的特点
数组和集合的区别
数组长度固定,集合长度不固定。数组类型固定,集合类型不固定。数组查找效率高,因为他的地址是连续的,通过索引可以快速找到某一个元素,但是数组的增删是效率极低的,因为其长度固定,所以增删的时候需要新建一个数组然后将原数组内容复制过来。
链表查询慢,增删快与数组刚好相反:,单链表是上个节点记得下个节点的地址,但下个节点记不住上个节点的地址,所以单向。增删元素只需改变节点的自身地址和下一个的地址即可。
树形结构,红黑树查询速度非常之快:
List集合
关于List集合为什么是“List list = new ArrayList();”定义而不是"Collection list = new ArrayList<>();"这样定义,原因是因为多态,后者运用了多态机制,无法调用ArrayList自身的方法和属性,还有就是List和Set集合的共同特点形成了Collection接口,Collection接口没有带索引的方法,List有带索引的方法。
List接口中的ArrayList接口适合查找,因为ArrayList是基于数组的操作,带有索引,不适合增删。LinKedList接口是基于链表的,适合增删,每次查找都从头开始,查找效率极低,当然还有更快的查询方式,在这里只是相比而言。
//三种遍历数组的方法********************
//for遍历
for (int i = 0; i < list.size(); i++) {
String s1 = list.get(i);
System.out.println(s1);
}
System.out.println("--------------");
//迭代器遍历
Iterator<String> it = list.iterator();
while (it.hasNext()){
String em = it.next();
System.out.println(em);
}
System.out.println("--------------");
//增强for遍历
for (String i :list) {
System.out.println(i);
}
LinkedList集合
Set集合
package cn.gather;
import java.util.*;
/**
* List集合:具有索引,可以有重复的数据,可以使用任何方式遍历结果。
* Set集合:没有索引,也没有带有索引的方法,不能使用普通的for循环遍历,也不能有重复的数据
*/
public class DemoList {
public static void main(String[] args ){
//arraylist();
//linkedlist();
hashset();
}
/**
*HashSet特点:
* 1.不允许重复
* 2.没有索引,也没有带索引的方法
* 3.是一个无序的集合,也就是插入和输出的顺序不一致
* 4,底层实现是一个哈希表,哈希表查询的速度非常快
*/
private static void hashset() {
HashSet<Integer> set = new HashSet<>();
//使用.add方法插入数据到哈希表中,add方法是Collection继承给Set接口的
set.add(1);
set.add(2);
set.add(3);
set.add(1);
//使用迭代器遍历
Iterator<Integer> it = set.iterator();
while (it.hasNext()){
Integer em = it.next();
System.out.println(em);
}
System.out.println("--------------");
//使用增强for循环遍历
for (Integer i : set) {
System.out.println(i);
}
}
/**
*LinkedList集合,是基于链表的集合,适合增删,都有带有索引的方法
*/
private static void linkedlist() {
LinkedList<String> link = new LinkedList<>();
link.push("a");
link.addFirst("a");
link.add("b");
//System.out.println(link.removeFirst());
System.out.println(link.removeFirst());
System.out.println(link.pop());
System.out.println(link.getFirst());
System.out.println(link);
}
/**
*ArrayList集合是基于数组产生的,具有索引,常用作查找功能
*/
private static void arraylist(){
List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("a");
System.out.println(list);
list.add(3,"2");
System.out.println(list);
String s = list.get(2);
System.out.println(s);
list.remove(1);
list.set(2,"d");
System.out.println(list);
System.out.println("--------------");
//for遍历
for (int i = 0; i < list.size(); i++) {
String s1 = list.get(i);
System.out.println(s1);
}
System.out.println("--------------");
//迭代器遍历
Iterator<String> it = list.iterator();
while (it.hasNext()){
String em = it.next();
System.out.println(em);
}
System.out.println("--------------");
//增强for遍历
for (String i :list) {
System.out.println(i);
}
}
}
哈希表对于没有定义的数据类型如User、Student必须重写Hashcode和equals方法
package cn.gather;
import java.util.*;
/**
* List集合:具有索引,可以有重复的数据,可以使用任何方式遍历结果。
* Set集合:没有索引,也没有带有索引的方法,不能使用普通的for循环遍历,也不能有重复的数据
*/
public class DemoList {
public static void main(String[] args ){
//arraylist();
//linkedlist();
//hashset();
/* HashSet<Person> set = new HashSet<>();//哈希表对于没有定义的数据类型需要重写Hashcode和equals方法
Person p1 = new Person("刘哥" ,23);
Person p2 = new Person("刘哥" ,23);
Person p3 = new Person("海哥" ,28);
set.add(p1);
set.add(p2);
set.add(p3);
System.out.println(set);*/
add(1,2,3,4,5,6);
mand(1,2,3,4,5,"sd","das",23);
}
private static void mand(Object...arr){
System.out.println(arr);
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
private static int add(int...arr){
System.out.println(arr);
System.out.println(arr.length);
int sum = 0;
for (int i = 0; i < arr.length; i++) {
sum = sum + arr[i];
}
System.out.println(sum);
return 0;
}
/**
*HashSet特点:
* 1.不允许重复
* 2.没有索引,也没有带索引的方法
* 3.是一个无序的集合,也就是插入和输出的顺序不一致
* 4,底层实现是一个哈希表,哈希表查询的速度非常快
*/
private static void hashset() {
HashSet<Integer> set = new HashSet<>();
//使用.add方法插入数据到哈希表中,add方法是Collection继承给Set接口的
set.add(1);
set.add(2);
set.add(3);
set.add(1);
//使用迭代器遍历
Iterator<Integer> it = set.iterator();
while (it.hasNext()){
Integer em = it.next();
System.out.println(em);
}
System.out.println("--------------");
//使用增强for循环遍历
for (Integer i : set) {
System.out.println(i);
}
}
/**
*LinkedList集合,是基于链表的集合,适合增删,都有带有索引的方法
*/
private static void linkedlist() {
LinkedList<String> link = new LinkedList<>();
link.push("a");
link.addFirst("a");
link.add("b");
//System.out.println(link.removeFirst());
System.out.println(link.removeFirst());
System.out.println(link.pop());
System.out.println(link.getFirst());
System.out.println(link);
}
/**
*ArrayList集合是基于数组产生的,具有索引,常用作查找功能
*/
private static void arraylist(){
List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("a");
System.out.println(list);
list.add(3,"2");
System.out.println(list);
String s = list.get(2);
System.out.println(s);
list.remove(1);
list.set(2,"d");
System.out.println(list);
System.out.println("--------------");
//for遍历
for (int i = 0; i < list.size(); i++) {
String s1 = list.get(i);
System.out.println(s1);
}
System.out.println("--------------");
//迭代器遍历
Iterator<String> it = list.iterator();
while (it.hasNext()){
String em = it.next();
System.out.println(em);
}
System.out.println("--------------");
//增强for遍历
for (String i :list) {
System.out.println(i);
}
}
}
可变参数:
//在集合中添加多个元素,并将其打乱
ArrayList<String> list01 = new ArrayList<>();
//在集合中添加多个元素 addall()
Collections.addAll(list,"1","a","heihua","b","df");
Collections.shuffle(list);
ArrayList<Integer> list01 = new ArrayList<>();
Collections.addAll(list01,1,2,3,3,2,7,4,5);
Collections.sort(list01);
System.out.println(list01);
ArrayList<String> list02 = new ArrayList<>();
Collections.addAll(list02,"c","g","a","me");
Collections.sort(list02);
System.out.println(list02);
ArrayList<Person> list03 = new ArrayList<>();//自己定义的类并没有重写Comp..。。方法
list03.add(new Person("张三",35));
list03.add(new Person("赵六",10));
list03.add(new Person("五把",33));
Collections.sort(list03);
System.out.println(list03);
********************************
//自己定义的类没有默认的排序,需要重写CompareTo方法
/*
重写CompareTo方法
更改排序规则
*/
@Override
public int compareTo(Person o) {
//自定义排序规则,比较年龄排序
return this.Age - o.Age;//升序
}
比较器
Map
HashSet和TreeSet比较
如果需要排序就用TreeSet,如果不需要比较就用HashSet。HashMap的运行速度比较快,如果不需要按照排序的话还是推荐HashMap。
Map接口中的常用方法
//Map集合迭代必须先转换成set集合再进行迭代
HashMap<String,String> map = new HashMap<>();
map.put("张飞","张翼德");
map.put("刘备","刘玄德");
map.put("曹操","曹孟德");
map.put("赵云","赵子龙");
map.put("周瑜","周公瑾");
// System.out.println(map.remove("张飞"));
System.out.println(map);
//System.out.println(map.get("关羽"));
//System.out.println(map.containsKey("关羽"));
**********************
//第一种遍历方法
Set<String> set = map.keySet();
for (String i : set) {
String s = map.get(i);
System.out.println(i+"="+s);
}
**********************
//第二种遍历方法
Set<Map.Entry<String, String>> set = map.entrySet();
for (Map.Entry i : set) {
System.out.println(i.getKey() + "=" + i.getValue());
}
关于Map集合存入Student的时候,如果key是Student那么student类必须重写equals和hashcode方法,如果key是String类则不用,这和上面的一个道理,如果自己定义的类牵扯到重复值的问题,那么久必须重写equals和hashcode方法。
代码如下:
//String类型做Key的值,不需要重写,Java自带
HashMap<String,Student> map = new HashMap<>();
map.put("张飞",new Student("张翼德",35));
map.put("孙权",new Student("孙仲谋",35));
map.put("袁绍",new Student("袁本初",35));
map.put("张飞",new Student("张",35));
//Student类做Key的值,必须重写方法
HashMap<Student,String> map = new HashMap<>();
map.put(new Student("张飞",23),"张翼德");
map.put(new Student("马超",23),"马孟起");
map.put(new Student("鲁肃",23),"鲁子敬");
map.put(new Student("张飞",23),"张");
//利用增强for循环来遍历HashMap集合
for (Map.Entry i:
map.entrySet()) {
System.out.println(i.getKey() + "=" + i.getValue());
}
package cn.gather;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
/**
*计算字符串中每个字符出现的次数
* 1.使用Scanner获取字符
* 2.创建map集合,key是字符串中的字符,value是字符出现的次数
* 3.通过字符串遍历,取出每一个元素
* 4.使用获取到得字符与map集合中的key判断有没有
* 5.key如果存在,在获取value,value++,不存在put方法,添加key和value,value=1;
* 6.遍历map集合输出结果
*/
public class DenoMapTest {
public static void main(String[] args ){
//输入一个字符串
Scanner input = new Scanner(System.in);
System.out.println("请输入一个集合:");
String x = input.next();
//建立Map集合
HashMap<Character,Integer> map = new HashMap<>();
//先将输入的字符串转化成一个字符串数组对数组进行遍历,与集合中的key进行比较,有的话value加一,没有的话用put存入
for (char i: x.toCharArray()) {
if (map.containsKey(i)){
Integer d = map.get(i);
d++;
map.put(i,d);
}else {
map.put(i,1);
}
}
//Map集合不能直接迭代,需要转化一下,我这里用了entryset类进行遍历
for (Map.Entry i:
map.entrySet()) {
System.out.println(i.getKey() + "=" + i.getValue());
}
}
}
斗地主综合案例升级版(添加看牌时排序功能)
代码如下:
package cn.gather;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
/**
* 斗地主综合案例升级版(实现了看牌时排序功能)
* 1.准备牌
* 2.洗牌
* 3.发牌
* 4.看牌
*/
public class DouDiZhuT {
public static void main(String[] args ){
/**
* 1.准备牌
*/
//先建立两个数组用来存放花色和数字,然后再对他们进行合并,插入Map数组
String[] colors ={
"♥","♣","♦","♠"};
String[] numbers = {
"2","A","K","Q","J","10","9","8","7","6","5","4","3"};
//建立一个Map数组,先存放大王和小王
HashMap<Integer,String> map = new HashMap<>();
//创建List集合对扑克牌进行洗牌,List集合里面放的是Map集合的索引
ArrayList<Integer> list = new ArrayList<>();
map.put(0,"大王");
map.put(1,"小王");
list.add(0);
list.add(1);
Integer k = 2;
for (String i : numbers) {
for (String j : colors) {
map.put(k,j+i);
list.add(k);
k = k +1;
}
}
//System.out.println(map);
//System.out.println(list);
/**
* 2.洗牌
*/
//对List集合进行乱序
Collections.shuffle(list);
//System.out.println(list);
/**
* 3.发牌
*/
ArrayList<Integer> player01 = new ArrayList<>();
ArrayList<Integer> player02 = new ArrayList<>();
ArrayList<Integer> player03 = new ArrayList<>();
ArrayList<Integer> dipai = new ArrayList<>();
//遍历List集合
for (int i = 0; i < list.size(); i++) {
Integer s = list.get(i);
if (i>=51){
dipai.add(s);
}else if (i%3==0){
player01.add(s);
}else if(i%3==1){
player02.add(s);
}else if(i%3==2){
player03.add(s);
}
}
//排序
Collections.sort(player01);
Collections.sort(player02);
Collections.sort(player03);
Collections.sort(dipai);
/**
* 4.看牌
*/
lookpoker("云长",map,player01);
lookpoker("翼德",map,player02);
lookpoker("玄德",map,player03);
lookpoker("底牌",map,dipai);
}
/**
*建立看牌的方法
* @param name : 玩家姓名
* @param map :存放扑克牌的Map集合
* @param list :存放索引的List集合
*/
public static void lookpoker(String name,HashMap<Integer,String> map,ArrayList<Integer> list){
//输出姓名
System.out.print(name + ": ");
//遍历玩家或者底牌集合,获取索引
for (Integer key : list) {
String value = map.get(key);
System.out.print(value + " ");
}
System.out.println();
}
}
结果:
彩蛋
此篇博客大都是我的笔记所写,包含一些我学集合的截图与代码,如有需要评论或私我要原版笔记~ 关于泛型的笔记链接点这里–>(笔记链接),自取~ 谢谢捧场~