匿名内部类和Lambda表达式

    匿名内部类:
                顾名思义是没有名字的内部类(inner class),这个类的作用大概就是让Java更人性化。
                当某个类只会使用一次时,创建一个类会显得很笨重呆板,所以就有了匿名内部类这个东西。
                看一段简短的代码:
interface melo  //定义一个接口
{
	public String Name();
}

public class Test {
   
	public void use(melo a)
	{ 
		System.out.println(a.Name());
	}
	public static void main(String[] args)
	{
		 Test a=new Test();
		 // use 方法需要一个melo 参数,但melo接口不能直接创建对象,所以需要一个实现
		 melo接口的类的对象。
		 
		 a.use(new melo()*{ 
			 public String Name()
			 { 
				 return "cgz";
			 }*
			 
		 });
	}
}

这是匿名内部类的写法,正常写法是:

class melon implements melo // 普通的有名字的实现melo接口的类
{ 
	public String Name()
	{
		return "cgz";
	}
}

a.use(new melon());

从经验就可以得到几个结论,匿名内部类需要创建对象所以不可以是抽象类。
匿名内部类没有名字,所以也不可能有构造函数。但是这句话也有例外…

abstract class melo
{
	private String name;     //name成员
	public melo(String name) {this.name=name;}   //构造函数
	public abstract void Name() ;    //抽象函数
	
	public String getName() {
		return name;
	}
}
public class Test {
   
	public void use(melo a)
	{ 
		a.Name();
	}
	
	public static void main(String[] args)
	{
		 Test a=new Test();
		 
		 a.use(new melo("cgz")  //此处用了父类的构造函数
		 {  
			 public void Name() 
			 {System.out.println(getName());}
		 });
	}
}






  public void boysAndGirls(List<Person> persons) {
        Map<Integer, Integer> result = persons.parallelStream().filter(p -> p.getAge()>=25 && p.getAge()<=35).
            collect(
                Collectors.groupingBy(p->p.getSex(), Collectors.summingInt(p->1))
        );
        System.out.print("boysAndGirls result is " + result);
        System.out.println(", ratio (male : female) is " + (float)result.get(Person.MALE)/result.get(Person.FEMALE));
    }



创建匿名内部类时,必须实现接口或抽象父类的所有抽象方法,甚至可以重写其中的普通方法。
另外一点,匿名内部类中访问的局部变量都已被显式或隐式的被final修饰,所以不可被改变。

关于lambda表达式,可以改写匿名内部类的代码使其更加简洁。
由编译器推断并帮你转换包装为常规的代码,因此你可以使用更少的代码来实现同样的功能

匿名内部类写法:

interface Command
{
	void process(int [] target);
}

class ProcessArray
{ 
	public void process(int [] target,Command cmd)
	{
		cmd.process(target);
	}
}
public class Test {
   
	public static void main(String[] args)
	{
		ProcessArray pa=new ProcessArray();
		int []target= {3,4,6,8};
		pa.process(target, new Command()
				{
		        public void process(int [] target)
		         { 
		               int sum=0;
		        for(int tmp:target)
		        {
		           sum+=tmp;
		       }
		        System.out.println(sum);
                }
				});
	}
}

Lambda写法:

public class Test {
	   
	public static void main(String[] args)
	{
		ProcessArray pa=new ProcessArray();
		int []target= {3,4,6,8};
		
		pa.process(target, (int [] array)->{
			 int sum=0;
		        for(int tmp:target)
		        {
		           sum+=tmp;
		       }
		        System.out.println(sum);
			
		});
	}
}

Lambda表达式没有像匿名内部类那样创建了一个对象,并且实现接口和抽象父类的方法。
基本语法为:

参数列表、箭头、Lambda主体。
(parameters) -> expression

或(请注意语句的花括号)

(parameters) -> { statements; }

其中Lambda表达式可以没有参数,当 { statements; } 语句块只有一句时可以省略花括号,
当(parameters)只有一个形参时,可以提省略圆括号。
当 { statements; }只有一句,表达式又需要返回值时,可以省略return。

最后一点尤为重要,它指明了lambda表达式的目标类型必须是函数式接口,函数式接口只能包含一个抽象方法。

// 首先Runnableu,是函数式接口,并且只有一个无参数的方法
用lambda表达式创建了一个lambda对象,实现了唯一的方法。
Runnable r=()->{ 
	for(int i=0;i<100;i++)
	{ 
		System.out.println();
	}
}

下面的代码看起来和上面的没啥区别,但他是错的,原因是Object不是函数式接口
Object obj=() ->{ 
for(int i=0;i<100;i++)
	{ 
		System.out.println();
	}
}

Arrays类的某些方法需要Comparator ,XxxOperator, XxxFunction等函数式接口。演示一下lambda表达式的用法

public static void main(String[] args)
	{
		
		String[] arr1=new String[] {"melo","pipihong","pipiwei","pipisheng","shuaishuaizhi"};
		Arrays.parallelSort(arr1, (o1,o2)->o1.length()-o2.length()); //用字符串长度排序
		System.out.println(Arrays.deepToString(arr1));
		int arr2[]=new int []{3,5,9,7,-5};
		Arrays.parallelPrefix(arr2,(left,right)->left*right);  //根据前两个元素的值计算当前元素的值
		System.out.println(Arrays.toString(arr2));
long []arr3=new long[5];
Arrays.parallelSetAll(arr3,operand->operand*5);//根据索引计算当前元素的值
System.out.println(Arrays.toString(arr3));
		
	}

最后Lambda表达式用法千变万化,最后分享一个map里的lambda用法

//给出一个String类型的数组,找出其中各个素数,并统计其出现次数
 public void primaryOccurrence(String... numbers) {
        List<String> l = Arrays.asList(numbers);  //把数组元素添加给表 
        Map<Integer, Integer> r = l.stream()
            .map(e -> new Integer(e))
            .filter(e -> Primes.isPrime(e))
            .collect( Collectors.groupingBy(p->p, Collectors.summingInt(p->1)) );
        System.out.println("primaryOccurrence result is: " + r);
    }


  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值