1.数组:
1.定义:
(1)在内存中 通过连续的存储单元 存储相同数据类型的 有序集合(2)数据类型[] 变量名;
2.声明:
(1)静态:new 数据类型[]{元素1,元素2,元素3,…}(2)动态:初始只指定数组的长度 然后通过索引一次填充具体的值。
**3.初始化: **
(1)变量名 = new 数据类型[数组的长度]; arrs = new int[10];4.获取元素:
(1)数组变量[索引] 索引从0开始 到 长度-1 结束**5.获取长度: **
(1)数组变量.length
代码1分析:
public class Test01 {
public static void main(String[] args) {
//静态初始化
int[] arrs=new int[] {1,12,123};
//动态初始化
String[] strs=new String[5];
strs[0] = "嘿嘿";
strs[1] = "哈哈";
strs[2] = "呵呵";
strs[3] = "xixi";
System.out.println(arrs[2]);
System.out.println(arrs.length);//打印出数组的长度
}
}
2.增强for循环:
1.使用方式:
for(数据类型 变量名:取出数据的变量){
}
2.作用: 只是用来获取元素的 迭代器
代码2分析:
public class Test03 {
public static void main(String[] args) {
// 往数组中添加元素 1 3 5 7 。。。。。99奇数
//1:声明一个数组
int[] arrs = new int[50];
//通过循环一次填充值
for(int i = 0;i<arrs.length;i++) {
arrs[i] = 2*i+1;
System.out.println("打印第一个位置上的元素:"+arrs[0]);
//普通for循环获取数组元素
for(int i = 0;i<arrs.length;i++) {
System.out.print(arrs[i]+"\t");
}
//增强for循环获取数组元素
for(int arr:arrs) {
System.out.println(arr);
}
}
}
3.策略模式:
1.匿名内部类:
(1)内部比较器: java.lang.Compareable 比较大小
(2)外部比较器: java.util.Comparator
(3)通过匿名内部类可以产生一个接口/抽象了的 实现类对象/子类对象
2.mvc 分层开发:
(1)m: modle 模型 实体对象 vo bean entity
(2)v: view 视图层
(3)c: controller 控制层
代码3分析:
例题:
(1)有一个数组 数组中存储的是Emp(员工)对象,员工有姓名 年龄 工资。(2)将数组中员工的工资大于2000 小于5000的员工信息罗列出来
(3)Emp类创建出来
代码:
1.实体层:
public class Emp {
// 私有属性
private String name;
private int sal;
private int age;
public Emp() {
}
public Emp(String name,int sal,int age) {
this.name = name;
this.sal = sal;
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public int getSal() {
return sal;
}
public void setSal(int sal) {
this.sal = sal;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String toString() {
return "EMP:name:"+this.name+"age:"+this.age+"sal:"+this.sal;
}
}
2.接口:
package com.mage.service;
import com.mage.vo.Emp;
@FunctionalInterface
public interface Filter {
public void filter(Emp[] emps);
}
3.接口实现类:
import com.mage.service.Filter;
import com.mage.vo.Emp;
public class FilterAge implements Filter{
@Override
public void filter(Emp[] emps) {
for(int i = 0;i<emps.length;i++) {
//获取数组中的每一个元素
if(emps[i].getAge()>=15 && emps[i].getAge()<=18) {
System.out.println(emps[i]);
}
}
}
}
4.测试类:
import com.mage.service.Filter;
import com.mage.service.impl.FilterAge;
import com.mage.vo.Emp;
public class Test05 {
public static void main(String[] args) {
//通过带参构造器创建对象
Emp emp1 = new Emp("张三",4500,22);
Emp emp2 = new Emp("李四",3300,19);
Emp emp3 = new Emp("王五",5555,33);
Emp emp4 = new Emp("赵六",7632,18);
Emp emp5 = new Emp("田七",2699,21);
//声明一个emp数组
Emp[] emps = new Emp[] {emp1,emp2,emp3,emp4,emp5};
//方法一
filter(new Filter() {
public void filter(Emp[] emps) {
for(int i = 0;i<emps.length;i++) {
//获取数组中的每一个元素
if(emps[i].getSal()>=2000 && emps[i].getSal()<=5000) {
System.out.println(emps[i]);
}
}
}
},emps);
//lamade
filter((x)->{
for(int i = 0;i<x.length;i++) {
//获取数组中的每一个元素
if(x[i].getSal()>=2000 && x[i].getSal()<=5000) {
System.out.println(x[i]);
}
}
},emps);
new Emp();
}
public static void filter(Filter filter,Emp[] emps) {
filter.filter(emps);
}
}
4.数组基本操作:
使用数值存储int类型的数据,并且提供相应的方法对数组中的数据进行增、删、改、查操作;
代码4分析:
package com.mage.arrayutil;
public class ArrayList {
private int[] arrs ;
private static final int DEFAULT_CAPACITY = 10;
//已存储的数组个数
private int size;
//底层数组arrs的长度
private int capacity;
public ArrayList(){
this(DEFAULT_CAPACITY);
}
public ArrayList(int capacity){
arrs=new int[capacity];
this.capacity=capacity;
this.size=0;
}
public int size(){
return this.size;
}
public int opacity(){
return arrs.length;
}
public boolean isEmpty(){
return this.size==0;
}
//在指定索引位置上添加元素
public void add(int value,int index){
//对于指定的索引位置需要先判断它是否在当前数组中
if(index<0||index>size){
System.out.println("这是不对的哦");
return;
}
//原始不允许数组进行扩容
/*if(size==arrs.length){
System.out.println("数组已经满了");
}*/
//当添加的元素达到了数组之前定义的长度时扩容
if(size==arrs.length){
dilatation(arrs.length*2);
}
//空出指定索引的位置,用于添加元素
for(int i=size;i>index;i--){
arrs[i]=arrs[i-1];
}
arrs[index]=value;
size++;
}
//在数组第一个位置上添加元素
public void addFist(int value){
add(value,0);
}
//在数组最后一个位置上添加元素
public void addLast(int value){
add(value,size);
}
//查询指定元素的索引值
public int select(int value){
for(int i=0;i<size-1;i++){
if(arrs[i]==value){
return i;
}
}
return -1;
}
//查询指定索引位置上的元素
public int get(int index){
//先需要判断指定的索引是否在数组索引中
if(index<0||index>=size){
System.out.println("这是不对的哦");
return -1;
}
return this.arrs[index];
}
//修改指定索引位置上的元素
public int modify(int index,int value){
//调用get方法先获取指定索引位置上的值
int num=get(index);
if(num!=-1){
arrs[index]=value;
return num;
}
return -2;
}
//删除指定索引位置上的元素
public int delete(int index){
//对于指定的索引位置需要先判断它是否在当前数组中
if(index<0||index>=size){
System.out.println("这是不对的哦");
return -1;
}
int del=arrs[index];
for(int i=index;i<size-1;i++){
arrs[i]=arrs[i+1];
}
size--;
arrs[size]=0;
//缩容
if(size==arrs.length/4&&arrs.length/2>0){
dilatation(arrs.length/2);
}
return del;
}
//删除第一个元素
public int deleteFirst(){
return delete(0);
}
//删除最后一个元素
public int deleteLast(){
return delete(size-1);//数组下标从0开始所以要减1
}
//对数组进行扩容dilatation
public void dilatation(int capacity){
//创建一个新的数组
int [] newArrs=new int[capacity];
//调用方法进行拷贝
copyOf(arrs,newArrs,Math.min(arrs.length, newArrs.length));
arrs=newArrs;
}
//定义一个私有的方法用于对数组进行拷贝
private void copyOf(int[] src,int[] dest,int min){
//先需要判定一下新数组与之前定义的数组是否为空,为空不拷贝
if(src==null||dest==null){
System.out.println("数组是空的");
return;
}
//判定一下新数组与之前定义的数组长度是否小于等于0,
if(src.length<=0||dest.length<=0){
System.out.println("数组长度不符合要求");
return;
}
//如果都满足条件开始copy
for(int i=0;i<min;i++){
dest[i]=src[i];
}
}
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("size:"+this.size+"opacity:"+this.arrs.length);
sb.append("[");
for(int i = 0;i<size;i++) {
sb.append(arrs[i]);
if(i!=size-1) {
sb.append(",");
}
}
sb.append("]");
return sb.toString();
}
}
测试类:
package com.mage.arrayutil;
public class ArrayUtil {
private ArrayUtil(){
}
//初始化:
public static void init(int[] arrs){
if(arrs!=null&&arrs.length!=0){
for(int i=0;i<arrs.length;i++){
arrs[i]=(int)(Math.random()*78+33);
}
}
}
public static String toString(int[] arrs){
StringBuffer s=new StringBuffer();
s.append("[");
for(int i=0;i<arrs.length;i++){
s.append(arrs[i]);
}
s.append("]");
return s.toString();
}
}
5.排序:
1.冒泡排序:
(1)原理:
1、每次都比较两个相邻的元素,如果前一个比后一个要大,就调换他们的位置;
2、对每一对相邻的元素做同样的操作,直到最后一对相邻元素对比完成那么最后一个数就是这些数中最大的数;
3、对所有的元素重复操作,除了最后一个,直到没有数需要比较;
(2)优点:
1、每进行一次排序就会少比较一次,在一定程度上减少了代码量。
代码5分析:
第一次只要求实现功能,未做优化。
package com.mage.Paixu;
//没有任何优化的冒泡排序
public class Bubble01 {
public static void main(String[] args) {
int[] arr={20,10,40,10,60,24,90};
bubbleSort01(arr);
}
//定义数组中冒泡排序的方法:n表示数组长度
public static void bubbleSort01(int[] arrs) {
System.out.println("原数组:"+toString(arrs));
for(int i=0;i<arrs.length-1;i++) {//控制趟数
System.out.println("第"+(i+1)+"趟");
for(int j=0;j<arrs.length-1;j++) {//次数
if(arrs[j]>arrs[j+1]) {
int temp = arrs[j];
arrs[j] = arrs[j+1];
arrs[j+1] = temp;
}
System.out.println("第"+(j+1)+"次:"+toString(arrs));
}
}
}
public static String toString(int[] arrs){
StringBuffer s=new StringBuffer();
s.append("[");
for(int i=0;i<arrs.length;i++){
s.append(arrs[i]);
}
s.append("]");
return s.toString();
}
}
运行结果:
由运行图不难看出在后期已经排好序了情况下还是进行了排序,为此开始考虑优化。
优化代码1:
package com.mage.Paixu;
/**
* 优化(1)
* 对于一个本身有序或者序列后面大部分有序的序列前一种会浪费
*/
public class Bubble02 {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] arr={20,10,40,10,60,24,90};
bubbleSort02(arr);
}
public static void bubbleSort02(int[] arrs) {
System.out.println("原数组:"+toString(arrs));
for(int i=0;i<arrs.length-1;i++) {//控制趟数
System.out.println("第"+(i+1)+"趟");
for(int j=0;j<arrs.length-1-i;j++) {//次数
if(arrs[j]>arrs[j+1]) {
int temp = arrs[j];
arrs[j] = arrs[j+1];
arrs[j+1] = temp;
}
System.out.println("第"+(j+1)+"次:"+toString(arrs));
}
}
}
public static String toString(int[] arrs){
StringBuffer s=new StringBuffer();
s.append("[");
for(int i=0;i<arrs.length;i++){
s.append(arrs[i]);
}
s.append("]");
return s.toString();
}
}
运行结果:
优化代码2:
package com.mage.Paixu;
public class bubble03 {
public static void main(String[] args) {
int[] arr={20,10,40,10,60,24,90};
bubbleSort03(arr);
}
public static void bubbleSort03(int[] arrs) {
System.out.println("原数组:"+toString(arrs));
for(int i=0;i<arrs.length-1;i++) {//控制趟数
//声明一个是否排好序
boolean isSorted = true;
System.out.println("第"+(i+1)+"趟");
for(int j=0;j<arrs.length-1-i;j++) {//次数
if(arrs[j]>arrs[j+1]) {
isSorted = false;
int temp = arrs[j];
arrs[j] = arrs[j+1];
arrs[j+1] = temp;
}
System.out.println("第"+(j+1)+"次:"+toString(arrs));
}
//判定
if(isSorted) {
break;
}
}
}
public static String toString(int[] arrs){
StringBuffer s=new StringBuffer();
s.append("[");
for(int i=0;i<arrs.length;i++){
s.append(arrs[i]);
}
s.append("]");
return s.toString();
}
}
运行结果:
优化代码3:
package com.mage.Paixu;
public class Bubble04 {
public static void main(String[] args) {
int[] arr={20,10,40,60,80,90};
bubbleSort04(arr);
}
public static void bubbleSort04(int[] arrs) {
System.out.println("原数组:"+toString(arrs));
//基准点
int index = arrs.length-1;
for(int i=0;i<arrs.length-1;i++) {//控制趟数
//声明一个是否排好序
boolean isSorted = true;
int tmp = 0;
System.out.println("第"+(i+1)+"趟");
for(int j=0;j<index;j++) {//次数
if(arrs[j]>arrs[j+1]) {
isSorted = false;
int temp = arrs[j];
arrs[j] = arrs[j+1];
arrs[j+1] = temp;
tmp = j;
}
System.out.println("第"+(j+1)+"次:"+toString(arrs));
}
index = tmp;
//判定
if(isSorted) {
break;
}
}
}
public static String toString(int[] arrs){
StringBuffer s=new StringBuffer();
s.append("[");
for(int i=0;i<arrs.length;i++){
s.append(arrs[i]);
}
s.append("]");
return s.toString();
}
}
运行结果:
2.选择排序:
(1)遍历元素找到一个最小(或最大)的元素,把它放在第一个位置,然后再在剩余元素中找到最小(或最大)的元素,把它放在第二个位置,依次下去,完成排序。
代码6分析:
public class Choice {
public static void main(String[] args) {
int[] arr={20,10,40,10,60,24,90};
choice(arr,arr.length);
for(int i=0;i<arr.length;i++){
System.out.print(arr[i]+"\t");
}
}
public static void choice(int[] a,int n){
for(int i=0;i<n-1;i++){
int min=i;//min代表的是最小值的索引位置
for(int j=i+1;j<n;j++){
if(a[j]<a[i]){
min=j;//比较出最小值的索引位置然后重新赋值给min
}
}
//判断当前最小值的索引位置是否和之前一样不一样的话交换值。
if(i!=min){
int temp;
temp=a[i];
a[i]=a[min];
a[min]=temp;
}
}
}
}
运行结果:
3.二分查找:
(1)原理:有序的序列,每次都以序列的中间位置与待查找的数进行比较,然后每次缩小一 半的范围,直到匹配成功。
(2)优点:优点是比较次数少,查找速度快,平均性能好;
缺点:要求待查表为有序表,且插入删除困难
代码7分析:
package com.mage.Paixu;
public class binSearch {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] arrs={10,30,40,50,60,70,80};
System.out.println(binSearch(arrs,40));
}
public static int binSearch(int[] arrs, int value) {
//声明索引
int max = arrs.length-1;
int min = 0;
int mid = 0;
//循环判定
while(min<=max) {
mid = (max+min)/2;
if(arrs[mid]>value) {
max = mid-1;
}else if(arrs[mid]<value) {
min = mid+1;
}else {
return mid;
}
}
return -1;
}
}
运行结果:
6.常见面试题:
可变参数:
可变参数:
提高代码的复用性
简化了开发
降低入参的复杂度
可变参数作为形式参数 一定是在当前形参的最后
可变参数作为形式参数 一定只有一个
可变参数在一定长度上可以代替相同类型 不同个数的 方法重载
面试题1分析:
public class Test {
public static void main(String[] args) {
int[] arrs = new int[] {2,3,4,5};
info(arrs);
info(2,3);
info("11",1,2,3,4,5);
}
public static void info(int ... arr) {
int sum = 0;
for(int ar:arr) {
sum+=ar;
}
System.out.println(sum);
}
//可变参 1.5
public static void info(String str,int ... arr) {
int sum = 0;
for(int ar:arr) {
sum+=ar;
}
System.out.println(sum);
}
// public static void info(int[] arr) {
// int sum = 0;
// for(int ar:arr) {
// sum+=ar;
// }
// System.out.println(sum); }
//
}
解析:
1.info(2,3); info(int … arr)会自动将参数(2,3)编译成数组类型;
2.info(String str,int … arr):可变参数作为形式参数 一定是在当前形参的最后
3.public static void info(int … arr)
public static void info(int[] arr)不能同时存在,不然编译器会以为是同一种方法。
面试题2分析:
在下列代码中哪些可以正常执行,调用哪个方法,哪些会报错
short s = 20;
fun(10,s);
System.out.println("====");
//F f = new S();
//f.fun(10,10);
S s1 = new S();
//s1.fun(10,10);
package com.mage.arrays;
class F{
void fun(int price,int ... discount){
System.out.println("F.fun");
}
}
class S extends F{
@Override
void fun(int price, int[] discount) {
System.out.println("S.fun");
}
}
public class Test00 {
public static void main(String[] args) {
short s = 20;
fun(10,s);
System.out.println("====");
//F f = new S();
//f.fun(10,10);
S s1 = new S();
//s1.fun(10,10);
}
public static void fun(int num1,int num2){
System.out.println("我是两个个参数的方法 int int");
}
public static void fun(int num1,long num2){
System.out.println("我是两个个参数的方法 int long");
}
public static void fun(int ... num){
System.out.println("我是个可变参数的方法");
}
}
解析:
1.short s = 20;
fun(10,s);
System.out.println("====");*(可以正常执行,根据最近最优原则调用fun(int num1,int num2)方法,在此处需注意虽然 public static void fun(int … num)方法可以自动将fun(10,s))解释成数组类型,但该方法一般都是最后考虑使用的,)
2.F f = new S();
f.fun(10,10);**(可以正常编译执行,父类类型的变量创建子类对象f,编译时看左边调用父类的fun(int price,int … discount)方法,第二个参数就变成了数组,然后调用了子类的fun(int price, int[] discount) **
S s1 = new S();
s1.fun(10,10);
(编译时就会报错,子类类型的子类对象,在调用fun(int price, int[] discount)时会参数类型不匹配)
面试3分析:
public class Test05 {
public static void main(String[] args) {
//调用该方法会出现什么问题
//fun("",null);
invoke(null,1);//会调用哪个方法呢?
}
public static void fun(String str,String ... strs){
System.out.println("str = [" + str + "], strs = [" + strs + "]");
}
public static void fun(String str,Integer ... ins){
System.out.println("str = [" + str + "], ins = [" + ins + "]");
}
static void invoke(Object obj,Object ... args ){
System.out.println("obj = [" + obj + "], args = [" + args + "]");
}
static void invoke(String str,Object obj,Object ... args){
System.out.println("str = [" + str + "], obj = [" + obj + "], args = [" + args + "]");
}
}
解析:
(1)fun("",null);编译会报错,fun(String str,String … strs)、fun(String str,Integer … ins)第可以一个参数类型都为String,因此比较第二个参数类型,但由于null可以赋值为任意引用类型,所以这两个方法优先度是一样的,编译器不知道选择哪个,因此这里会报错。
(2)invoke(null,1):会调用invoke(String str,Object obj,Object … args);根据第一参数类型,虽然null可以给任意类型赋值但String是Object的子类因此String更优先,Object … args可以不用给参数。
总结:
对于重载方法而言:
- 1:可变参数最后调
- 2:基本类型 最近最优(byte short int long float double)
- 3:引用类型 最近最优(多个从在方法参数列表中的形式参数存在继承关系,一定调用子类的重载方法) null