首页 文章 精选 留言 我的

精选列表

搜索[demo],共9497篇文章
优秀的个人博客,低调大师

DEMO:呼吸灯按钮、smoothbutton、使用一组图片设置按钮背景、setLevel

1.attrs属性: 1 2 3 4 5 6 7 8 9 10 11 12 <?xmlversion= "1.0" encoding= "utf-8" ?> <resources> <stringname= "app_name" >EX_templete</string> <stringname= "action_settings" >Settings</string> <stringname= "hello_world" >Helloworld!</string> <declare-styleablename= "SmoothButton" > <attrname= "transitionDrawable" format= "reference" /> <attrname= "transitionDrawableLength" format= "integer" /> <attrname= "transitionTextColorUp" format= "color" /> <attrname= "transitionTextColorDown" format= "color" /> </declare-styleable> </resources> 2.layout设置: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 <RelativeLayoutxmlns:android= "http://schemas.android.com/apk/res/android" xmlns:misc= "http://schemas.android.com/apk/res/com.example.ex_templete" xmlns:tools= "http://schemas.android.com/tools" android:layout_width= "match_parent" android:layout_height= "match_parent" android:paddingBottom= "@dimen/activity_vertical_margin" android:paddingLeft= "@dimen/activity_horizontal_margin" android:paddingRight= "@dimen/activity_horizontal_margin" android:paddingTop= "@dimen/activity_vertical_margin" tools:context= ".MainActivity" > <TextView android:id= "@+id/textView1" android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:text= "@string/hello_world" /> <com.example.ex_templete.SmoothButton android:layout_width= "fill_parent" android:layout_height= "wrap_content" android:background= "@drawable/red_button" android:text= "smoothbutton1" misc:transitionDrawable= "@drawable/red_transition_list" misc:transitionDrawableLength= "8" misc:transitionTextColorDown= "#aaa" misc:transitionTextColorUp= "#eee" /> </RelativeLayout> 3.自定义控件SmoothButton类: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 import android.content.Context; import android.content.res.TypedArray; import android.graphics.Color; import android.graphics.drawable.Drawable; import android.graphics.drawable.LevelListDrawable; import android.os.Handler; import android.os.Message; import android.util.AttributeSet; import android.view.KeyEvent; import android.view.MotionEvent; import android.widget.Button; public class SmoothButton extends Button { private static final long DELAY= 25 ; private int transitionDrawableLength; private int level; private int []colors; private boolean wasPressed; private Drawablebackground; public SmoothButton(Contextcontext,AttributeSetattrs) { super (context,attrs); TypedArraya=context.obtainStyledAttributes(attrs,R.styleable.SmoothButton); LevelListDrawabletransitionDrawable=(LevelListDrawable)a.getDrawable(R.styleable.SmoothButton_transitionDrawable); transitionDrawableLength=a.getInt(R.styleable.SmoothButton_transitionDrawableLength, 0 ); int useTextColors= 0 ; int c0= 0 ; if (a.hasValue(R.styleable.SmoothButton_transitionTextColorUp)) { c0=a.getColor(R.styleable.SmoothButton_transitionTextColorUp, 0 ); useTextColors++; } int c1= 0 ; if (useTextColors== 1 &&a.hasValue(R.styleable.SmoothButton_transitionTextColorDown)) { c1=a.getColor(R.styleable.SmoothButton_transitionTextColorDown, 0 ); useTextColors++; } a.recycle(); if (transitionDrawable== null ) { throw new RuntimeException( "transitionDrawablemustbedefinedinXML(withvalidxmlns)" ); } if (transitionDrawableLength== 0 ) { throw new RuntimeException( "transitionDrawableLengthmustbedefinedinXML(withvalidxmlns)" ); } if (useTextColors== 2 ) { setTextColor(c0); int a0=Color.alpha(c0); int r0=Color.red(c0); int g0=Color.green(c0); int b0=Color.blue(c0); int a1=Color.alpha(c1); int r1=Color.red(c1); int g1=Color.green(c1); int b1=Color.blue(c1); colors= new int [transitionDrawableLength]; for ( int i= 0 ;i<transitionDrawableLength;i++) { int ai=a0+i*(a1-a0)/transitionDrawableLength; int ri=r0+i*(r1-r0)/transitionDrawableLength; int gi=g0+i*(g1-g0)/transitionDrawableLength; int bi=b0+i*(b1-b0)/transitionDrawableLength; colors[i]=Color.argb(ai,ri,gi,bi); } } int []viewAttrs= {android.R.attr.background}; a=context.obtainStyledAttributes(attrs,viewAttrs); boolean hasa.hasValue( 0 ); a.recycle(); if (!hasBackground) { int l=getPaddingLeft(); int t=getPaddingTop(); int r=getPaddingRight(); int b=getPaddingBottom(); setBackgroundDrawable(transitionDrawable); setPadding(l,t,r,b); } background=getBackground(); level= 0 ; background.setLevel(level); //通过此方法设置一组图片为背景************************************** } @Override public boolean onKeyDown( int keyCode,KeyEventevent) { boolean rc= super .onKeyDown(keyCode,event); if ((keyCode==KeyEvent.KEYCODE_ENTER||keyCode==KeyEvent.KEYCODE_DPAD_CENTER)&&event.getRepeatCount()== 0 &&level+ 1 <transitionDrawableLength) { handler.removeMessages(- 1 ); handler.sendEmptyMessageDelayed( 1 ,DELAY); } return rc; } @Override public boolean onKeyUp( int keyCode,KeyEventevent) { boolean rc= super .onKeyUp(keyCode,event); if ((keyCode==KeyEvent.KEYCODE_ENTER||keyCode==KeyEvent.KEYCODE_DPAD_CENTER)&&event.getRepeatCount()== 0 &&level> 0 ) { handler.removeMessages( 1 ); handler.sendEmptyMessageDelayed(- 1 ,DELAY); } return rc; } @Override public boolean onTouchEvent(MotionEventevent) { wasPressed=isPressed(); boolean rc= super .onTouchEvent(event); post(checkPressed); return rc; } RunnablecheckPressed= new Runnable() { public void run() { if (!wasPressed&&isPressed()) { if (level+ 1 <transitionDrawableLength) { handler.removeMessages(- 1 ); handler.sendEmptyMessageDelayed( 1 ,DELAY); } } else if (wasPressed&&!isPressed()) { if (level> 0 ) { handler.removeMessages( 1 ); handler.sendEmptyMessageDelayed(- 1 ,DELAY); } } } }; private Handlerhandler= new Handler() { @Override public void handleMessage(Messagemsg) { int what=msg.what; level+=what; if (level>= 0 &&level<transitionDrawableLength) { background.setLevel(level); if (colors!= null ) { setTextColor(colors[level]); } sendEmptyMessageDelayed(what,DELAY); } else { level=Math.max( 0 ,level); level=Math.min(transitionDrawableLength- 1 ,level); } } }; } 4.MainActivity 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import android.os.Bundle; import android.app.Activity; import android.view.Menu; public class MainActivity extends Activity { @Override protected void onCreate(BundlesavedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @Override public boolean onCreateOptionsMenu(Menumenu) { getMenuInflater().inflate(R.menu.main,menu); return true ; } } 本文转自 glblong 51CTO博客,原文链接:http://blog.51cto.com/glblong/1228577,如需转载请自行联系原作者

优秀的个人博客,低调大师

DEMO:transition3d、运用动画实现图片3d翻转效果

模仿系统apiDemos里的范例,去掉了listview,修改为点击图片后,更新图片并播放3d翻转动画。 代码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 package com.example.aexh_11_transition3d; import android.os.Bundle; import android.app.Activity; import android.view.Menu; import android.view.View; import android.view.ViewGroup; import android.view.View.OnClickListener; import android.view.animation.AccelerateInterpolator; import android.view.animation.Animation; import android.view.animation.DecelerateInterpolator; import android.view.animation.Animation.AnimationListener; import android.widget.ImageView; public class MainActivity extends Activity implements OnClickListener { /** * 仿照系统的范例,修改成点击图片播放动画更新图片。 * apiDemos范例: com.example.android.apis.animation * Transition3d */ private static final int [] PHOTOS_RESOURCES = new int [] { R.drawable.photo1, R.drawable.photo2, R.drawable.photo3, R.drawable.photo4, R.drawable.photo5, R.drawable.photo6 }; private ImageView mImageview; private ViewGroup mLayout; private int mPosition; @Override protected void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); mImageview = (ImageView) findViewById(R.id.imageView1); mImageview.setOnClickListener( this ); mLayout = (ViewGroup) findViewById(R.id.image_layout); // ViewGroup是所有layout的父类 /** * 下面这句应该是用来压缩大图的,没加上这句运行正常 */ // Since we are caching large views, we want to keep their cache // between each animation mLayout.setPersistentDrawingCache(ViewGroup.PERSISTENT_ANIMATION_CACHE); } @Override public void onClick(View v) { if (v.getId() == R.id.imageView1) { // Pre-load the image then start the animation mPosition++; applyRotation( 0 , 90 ); mImageview.setImageResource(PHOTOS_RESOURCES[mPosition % 6 ]); } } /** * Setup a new 3D rotation on the container view. * * @param position * the item that was clicked to show a picture, or -1 to show the * list * @param start * the start angle at which the rotation must begin * @param end * the end angle of the rotation */ private void applyRotation( float start, float end) { // Find the center of the container final float centerX = mLayout.getWidth() / 2 .0f; final float centerY = mLayout.getHeight() / 2 .0f; // Create a new 3D rotation with the supplied parameter // The animation listener is used to trigger the next animation final Rotate3dAnimation rotation = new Rotate3dAnimation(start, end, centerX, centerY, 310 .0f, true ); rotation.setDuration( 500 ); rotation.setFillAfter( true ); rotation.setInterpolator( new AccelerateInterpolator()); // 监听动画 rotation.setAnimationListener( new AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationRepeat(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { mLayout.post(mAaction); // 刷新layout这个View } }); // 启动动画 mLayout.startAnimation(rotation); } Runnable mAaction = new Runnable() { @Override public void run() { final float centerX = mLayout.getWidth() / 2 .0f; final float centerY = mLayout.getHeight() / 2 .0f; Rotate3dAnimation rotation; // mImageView.requestFocus(); rotation = new Rotate3dAnimation( 90 , 180 , centerX, centerY, 310 .0f, false ); rotation.setDuration( 500 ); rotation.setFillAfter( true ); rotation.setInterpolator( new DecelerateInterpolator()); mLayout.startAnimation(rotation); } }; } 系统实现的动画方法: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 package com.example.aexh_11_transition3d; /* * Copyright (C) 2007 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import android.view.animation.Animation; import android.view.animation.Transformation; import android.graphics.Camera; import android.graphics.Matrix; /** * An animation that rotates the view on the Y axis between two specified * angles. This animation also adds a translation on the Z axis (depth) to * improve the effect. */ public class Rotate3dAnimation extends Animation { private final float mFromDegrees; private final float mToDegrees; private final float mCenterX; private final float mCenterY; private final float mDepthZ; private final boolean mReverse; private Camera mCamera; /** * Creates a new 3D rotation on the Y axis. The rotation is defined by its * start angle and its end angle. Both angles are in degrees. The rotation * is performed around a center point on the 2D space, definied by a pair of * X and Y coordinates, called centerX and centerY. When the animation * starts, a translation on the Z axis (depth) is performed. The length of * the translation can be specified, as well as whether the translation * should be reversed in time. * * @param fromDegrees * the start angle of the 3D rotation * @param toDegrees * the end angle of the 3D rotation * @param centerX * the X center of the 3D rotation * @param centerY * the Y center of the 3D rotation * @param reverse * true if the translation should be reversed, false otherwise */ public Rotate3dAnimation( float fromDegrees, float toDegrees, float centerX, float centerY, float depthZ, boolean reverse) { mFromDegrees = fromDegrees; mToDegrees = toDegrees; mCenterX = centerX; mCenterY = centerY; mDepthZ = depthZ; mReverse = reverse; } @Override public void initialize( int width, int height, int parentWidth, int parentHeight) { super.initialize(width, height, parentWidth, parentHeight); mCamera = new Camera(); } @Override protected void applyTransformation( float interpolatedTime, Transformation t) { final float fromDegrees = mFromDegrees; float degrees = fromDegrees + ((mToDegrees - fromDegrees) * interpolatedTime); final float centerX = mCenterX; final float centerY = mCenterY; final Camera camera = mCamera; final Matrix matrix = t.getMatrix(); camera.save(); if (mReverse) { camera.translate(0.0f, 0.0f, mDepthZ * interpolatedTime); } else { camera.translate(0.0f, 0.0f, mDepthZ * (1.0f - interpolatedTime)); } camera.rotateY(degrees); camera.getMatrix(matrix); camera.restore(); matrix.preTranslate(-centerX, -centerY); matrix.postTranslate(centerX, centerY); } } 本文转自 glblong 51CTO博客,原文链接:http://blog.51cto.com/glblong/1226205,如需转载请自行联系原作者

优秀的个人博客,低调大师

告别Demo!聊聊AI技术从实验环境走向业务生产环境全过程

不知道你有没有过这种经历:在Jupyter Notebook里跑通了一个AI应用,效果惊艳,老板看了直点头,当场拍板"下周上线"。然后你兴冲冲地开始做生产化改造,结果发现——原来的100行代码要重写成1000行,原来笔记本里随便定义的变量要变成严格的配置管理,原来"能跑就行"的逻辑要加上各种异常处理……最后折腾了一个月才真正上到生产环境。

优秀的个人博客,低调大师

如何基于开源 demo 在 Web 端实现一个多人数独游戏

本文作者是声网社区的开发者“tjss”。他基于Vue、声网的互动白板的代码模板,搭建出了一个支持多人互动的数独游戏。本文记录了他的实现过程,欢迎大家也可以尝试实现自己的小游戏或应用。 我基于声网互动白板的 SDK 与 Window Manager 开发了一个场景化窗口插件,实现了一个多人数独游戏。在游戏中,每个玩家进入白板房间,都能看到数独游戏插件,同时可以参与其中,与房间内的小伙伴一起完成数独解题。 前期准备 1、注册一个声网账号,并实名认证,以便在后台创建项目,获取开发时会用到的 Appid 和 Token 2、了解 Vue 开发的基础知识。 3、了解声网互动白板产品,一些基本的接口和功能,看官方文档就足够了。 4、搭建开发环境: NodeJs 版本 16.0.0 @Vue/cli 4.5.1 VSCode 代码开发工具 开启和配置互动白板服务 首先我们需要一个实名认证的声网账号,进入控制台(console.agora.io),在声网控制台开启互动白板服务。 这里需要注意的是互动白板是作为服务而显示的,而控制台中只是显示项目列表,并没有直接显示服务。 这时候我们就先创建一个项目,然后点击“配置”进入到项目详情中,在里面的页面就可以看到服务内容了。 这时候找到互动白板服务,点击开启就行。因为我的已经开启了,所以显示的是配置按钮。 使用官网提供的代码模板 场景化窗口插件目前我们不需要从零开始建立的,声网提供了一个代码模板,基于此模板我们可以很轻松就能实现一个在互动白板上使用的插件。 模板地址:https://github.com/netless-io/community-app-template 当搭建好开发环境后,便可以下载模板代码了,通过 Git 或者下载 Zip 都行。 需要注意 README.md 中的开发环境配置: 1、在 .env 文件里配置白板房间 UUID 和 Token请将本目录下的 .env.example 文件复制一份,重命名为 .env 或 .env.local 后,在里面填写必须的白板配置信息。你可以在声网互动白板官方的 Netless Workshop 申请专用的白板配置。 2、执行 npm install 安装依赖 3、执行 npm start 进行本地开发 项目结构 笔者是基于 Vue 版本的插件模板进行开发的,直接打开项目,修改 src 里的内容即可,基本上和 Vue 开发一致。如果是通过 Git 命令拉取的代码,需要切换分支为 Vue 分支。 项目结构如下: playground 目录是基本不用修改的,我们实现的插件是在 src 目录中完成的。 index.ts 文件是我们插件的一些数据设置,比如插件名称。其他逻辑基本不用修改。 onst Sudoku: NetlessApp = { kind: "Sudoku", setup(context) { const box = context.getBox(); box.mountStyles(styles); const $content = document.createElement("div"); $content.className = "app-counter"; box.mountContent($content); const app = createApp(App).provide("context", context); app.mount($content); context.emitter.on("destroy", () => { app.unmount(); }); }, }; export default Sudoku; 数独游戏规则 数独网格由 9x9 个空格组成。玩家只能使用数字 1 到 9,每个 3×3 宫只能包含数字 1 到 9,每一列只能包含数字 1 到 9,每一行只能包含数字 1 到 9,每个 3×3 宫、每一列或每一行中的每个数字只能使用一次。当所有数独网格都填入正确的数字时,游戏结束。(摘自网上) 数据同步核心思路 1、通过互动白板SDK提供的 createStorage 方法,初始化一个数独棋盘,并把数据存储起来,同时需要更新自己的 chessBoard。 const chessBoard = ref(); const context = inject<AppContext>("context"); const storage = context.createStorage("chessBoard", { chessBoard: ChessBoard.init() }); chessBoard.value = deepCopy(storage.state.chessBoard) 2、在 Vue 界面的 onMounted 回调函数中添加存储值的更新监听,这样玩家在填格子的时候广播了最新的格子数据,其他玩家就能收到更新的通知,然后重新渲染界面。 onMounted(() => { initAppData() storage.addStateChangedListener((diff) => { chessBoard.value = deepCopy(diff.chessBoard?.newValue) if (finish(chessBoard.value.gridItems)) { statistics(chessBoard.value.gridItems) finishTag.value = true } }) }); 3、填格子的时候,通过 SDK 的 setState 方法去更新数独棋盘的数据。 if (e.data && e.data > 0) { grid.number = parseInt(e.data) grid.userId = uid.value grid.color = rgb } else { grid.number = 0 grid.userId = '' grid.color = new Rgb(233, 233, 233) } storage.setState({ chessBoard: chessBoard.value }) 数独游戏界面 笔者是优先实现这个互动游戏的核心功能,所以设计出的游戏界面比较简陋。 数独的数据结构 export class ChessBoard { gridItems: GridItem[][] } 因为需要统计游戏结束后,各个玩家填写的个数,所以在更新格子数值的时候也记录一下是哪一位玩家填写了。default 字段表示该格子是自动生成的,不需要玩家填写了。 export class GridItem { number: number color: Rgb userId: string default: boolean } 运行项目 点击工具栏最下方的按钮,可以找到我们实现的插件icon,然后点击即可打开。 打开插件后,会初始化创建一个数独题目,并且通过 createStorage 方法储存起来,所有进入房间的玩家都能拿到这个数据,后续数独的更新都会同步给玩家去修改。因为这个项目重点是学习一下插件开发与数据同步,所以游戏界面以及内容这些做的比较简单。 接下来就要打开多个网页并且输入 localhost:3000 进入我们的互动白板房间了,因为模板的uid是随机生成的,也就表示有不同的玩家进入了。 别的玩家填写后,其他玩家是不能再填这个格子的,最后游戏结束的时候,会统计各个玩家所填对的数字并展示。 游戏结束 总结 通过官方提供的场景化插件模板,我们很容易实现一些好玩的互动场景的功能。在这个简单的项目中,由于时间仓促,还没来得及优化得更好,后续有时间的时候笔者再打磨一下。比如不同玩家填写的数字以不同的颜色区分,增加限时机制等等。感兴趣的朋友一起来开发一些好玩的实时互动功能吧~ 现注册声网账号下载 SDK,可获得每月免费 10000 分钟使用额度。如在开发过程中遇到疑问,可在声网开发者社区与官方工程师交流。

优秀的个人博客,低调大师

会员卡模板查询接口(alipay.marketing.card.template.query)JAVA版本demo

说明: 该接口主要用于查询已创建的会员卡模板参数详细信息,官方接口文档请点击【会员卡模板查询接口】 创建模板接口参考该贴:[url]https://openclub.alipay.com/read.php?tid=1577&fid=71[/url] 修改模板接口参考该贴:[url]https://openclub.alipay.com/read.php?tid=4503&fid=71[/url]代码调用示例: //alipay.marketing.card.template.query (会员卡模板查询接口) public static void template_query(){ AlipayClient alipayClient=alipa

优秀的个人博客,低调大师

会员卡模板修改接口(alipay.marketing.card.template.modify)JAVA版本demo

说明: 该接口主要用于创建之后的会员卡的模板修改,官方接口文档请点击【会员卡模板修改】 创建模板接口请参考我的这个帖子:[url]https://openclub.alipay.com/read.php?tid=1577&fid=71[/url]接口调用示例: //alipay.marketing.card.template.modify (会员卡模板修改) public static void template_modify(){ AlipayClient alipayClient=alipayclient(); AlipayMarketingCardTemplateModifyRequest request = new AlipayMarketingCardTe

优秀的个人博客,低调大师

MapReduce对交易日志进行排序的Demo(MR的二次排序)

1.日志源文件 (各个列分别是: 账户,营业额,花费,日期) zhangsan@163.com 6000 0 2014-02-20 lisi@163.com 2000 0 2014-02-20 lisi@163.com 0 100 2014-02-20 zhangsan@163.com 3000 0 2014-02-20 wangwu@126.com 9000 0 2014-02-20 wangwu@126.com 0 200 2014-02-20 想要的结果: (计算出每个账户的总营业额和总花费,要求营业额排序降序,如果营业额相同则花费少的在上面) zhangsan@163.com 9000 0 9000 wangwu@126.com 9000 200 8800 lisi@163.com 2000 100 1900 2.写代码: InfoBean.java 对账户的后三个字段封装成一个Bean对象 1 import java.io.DataInput; 2 import java.io.DataOutput; 3 import java.io.IOException; 4 5 import org.apache.hadoop.io.WritableComparable; 6 7 //要和其他的InfoBean类型进行比较,所以此处泛型T为InfoBean 8 public class InfoBean implements WritableComparable<InfoBean> { 9 10 private String account; 11 private double income; 12 private double expenses; 13 private double surplus; 14 15 /* 16 *如果不写这个方法,封装InfoBean对象的时候就要分别set这个对象的各个属性. 17 */ 18 public void set(String account,double income,double expenses){ 19 this.account = account; 20 this.income = income; 21 this.expenses = expenses; 22 this.surplus = income -expenses; 23 } 24 @Override 25 public void write(DataOutput out) throws IOException { 26 out.writeUTF(account); 27 out.writeDouble(income); 28 out.writeDouble(expenses); 29 out.writeDouble(surplus); 30 } 31 32 @Override 33 public void readFields(DataInput in) throws IOException { 34 this.account = in.readUTF(); 35 this.income = in.readDouble(); 36 this.expenses = in.readDouble(); 37 this.surplus = in.readDouble(); 38 } 39 40 @Override 41 public int compareTo(InfoBean o) { 42 if(this.income == o.getIncome()){ 43 return this.expenses > o.getExpenses() ? 1 : -1; 44 } else { 45 return this.income > o.getIncome() ? -1 : 1; 46 } 47 } 48 49 @Override 50 //toString()方法输出的格式最好和源文件trade_info.txt中的格式一样, 字段通过Tab键分隔. 51 //而且在SumReducer类输出k3,v3的时候会输出k3(context.write(key, v);) 所以这个地方没有必要再输出k3(account) 52 public String toString() { 53 // return "InfoBean [account=" + account + ", income=" + income 54 // + ", expenses=" + expenses + ", surplus=" + surplus + "]"; 55 return this.income + "\t" + this.expenses+"\t" + this.surplus; 56 } 57 public double getIncome() { 58 return income; 59 } 60 61 public void setIncome(double income) { 62 this.income = income; 63 } 64 65 public double getExpenses() { 66 return expenses; 67 } 68 69 public void setExpenses(double expenses) { 70 this.expenses = expenses; 71 } 72 73 public double getSurplus() { 74 return surplus; 75 } 76 77 public void setSurplus(double surplus) { 78 this.surplus = surplus; 79 } 80 81 public String getAccount() { 82 return account; 83 } 84 85 public void setAccount(String account) { 86 this.account = account; 87 } 88 89 } SumStep.java 1 import java.io.IOException; 2 3 import org.apache.hadoop.conf.Configuration; 4 import org.apache.hadoop.fs.Path; 5 import org.apache.hadoop.io.LongWritable; 6 import org.apache.hadoop.io.Text; 7 import org.apache.hadoop.mapreduce.Job; 8 import org.apache.hadoop.mapreduce.Mapper; 9 import org.apache.hadoop.mapreduce.Reducer; 10 import org.apache.hadoop.mapreduce.lib.input.FileInputFormat; 11 import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; 12 13 public class SumStep { 14 15 public static class SumMapper extends Mapper<LongWritable, Text, Text, InfoBean>{ 16 private Text k = new Text(); 17 private InfoBean bean = new InfoBean(); 18 19 @Override 20 protected void map(LongWritable key, Text value,Mapper<LongWritable, Text, Text, InfoBean>.Context context) 21 throws IOException, InterruptedException { 22 23 String line = value.toString(); 24 String [] fields = line.split("\t"); 25 String account = fields[0]; 26 double income = Double.parseDouble(fields[1]); 27 double expenses = Double.parseDouble(fields[2]); 28 k.set(account); 29 bean.set(account, income, expenses); 30 context.write(k, bean); 31 } 32 } 33 public static class SumReducer extends Reducer<Text, InfoBean, Text, InfoBean>{ 34 private InfoBean v = new InfoBean(); 35 @Override 36 protected void reduce(Text key, Iterable<InfoBean> values,Reducer<Text, InfoBean, Text, InfoBean>.Context context) 37 throws IOException, InterruptedException { 38 double sum_in = 0; 39 double sum_out = 0; 40 for(InfoBean bean : values){ 41 sum_in += bean.getIncome(); 42 sum_out += bean.getExpenses(); 43 } 44 /* 45 * 在crxy的流量统计的案例中 是如下的方式写出k3和v3的 在reduce方法中new这个封装好的对象. 46 * 但是如果数据量比较大的情况下 是可能会造成内存溢出的. 47 * TrafficWritable v3 = new TrafficWritable(t1, t2, t3, t4); 48 * context.write(k2, v3); 49 * 50 * 所以建议把这个封装的对象写在"脑袋顶上" 如上所示....private InfoBean v = new InfoBean(); 51 * 但是如果你Java基础比较好的话可能会说 在Java中是引用传递...所以后面的v会覆盖前面的v,造成最后只有最有一个v 52 * 其实这里是不会产生问题的,因为context.write()方法会直接把v3对应的InfoBean对象序列化. 53 * 虽然之前对象的引用确实覆盖了,但是之前对象的值等都保存了下来.是可以放在这个类的"脑袋顶上"的. 54 * 让这个类公用这个InfoBean对象. 55 */ 56 57 v.set(key.toString(),sum_in,sum_out); 58 context.write(key, v); 59 } 60 } 61 public static void main(String[] args) throws Exception { 62 Configuration conf = new Configuration(); 63 Job job = Job.getInstance(conf); 64 job.setJarByClass(SumStep.class); 65 66 job.setMapperClass(SumMapper.class); 67 //以下两行可以在满足一定条件的时候省略掉. 68 //在满足k2和k3,v2和v3一一对应的时候就可以省略掉. 看SumReducer类所在行的泛型. 69 job.setMapOutputKeyClass(Text.class); 70 job.setMapOutputValueClass(InfoBean.class); 71 72 FileInputFormat.setInputPaths(job, new Path(args[0])); 73 74 job.setReducerClass(SumReducer.class); 75 job.setOutputKeyClass(Text.class); 76 job.setOutputValueClass(InfoBean.class); 77 FileOutputFormat.setOutputPath(job, new Path(args[1])); 78 job.waitForCompletion(true); 79 } 80 } 项目打成jar包放到Linux中,日志源文件上传到HDFS上.运行结果如下: hadoop jar /root/itcastmr.jar itcastmr.SumStep /user/root/trade_info.txt /tradeout 但是这个结果并没有排序.还是按照账号的字典排序. 以这个MR的输出当做输入对其根据InfoBean对象进行排序..... 上代码SortStep.java: 1 import java.io.IOException; 2 3 import org.apache.hadoop.conf.Configuration; 4 import org.apache.hadoop.fs.Path; 5 import org.apache.hadoop.io.LongWritable; 6 import org.apache.hadoop.io.NullWritable; 7 import org.apache.hadoop.io.Text; 8 import org.apache.hadoop.mapreduce.Job; 9 import org.apache.hadoop.mapreduce.Mapper; 10 import org.apache.hadoop.mapreduce.Reducer; 11 import org.apache.hadoop.mapreduce.lib.input.FileInputFormat; 12 import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; 13 14 public class SortStep { 15 //这个Mapper读取的HDFS文件是SumStep Reduce计算输出的文件. 16 public static class SortMapper extends Mapper<LongWritable, Text, InfoBean, NullWritable>{ 17 private InfoBean k = new InfoBean(); 18 @Override 19 protected void map(LongWritable key,Text value,Mapper<LongWritable, Text, InfoBean, NullWritable>.Context context) 20 throws IOException, InterruptedException { 21 String line = value.toString(); 22 String [] fields = line.split("\t"); 23 String account = fields[0]; 24 double income = Double.parseDouble(fields[1]); 25 double expenses = Double.parseDouble(fields[2]); 26 k.set(account, income, expenses); 27 //现在是要求按照InfoBean对象中的规则排序(InfoBean中有compareTo方法)...所以InfoBean对象当做k2... 28 context.write(k,NullWritable.get());//不能传null,NullWritable.get() 是获得的this对象. 29 } 30 } 31 public static class SortReducer extends Reducer<InfoBean, NullWritable, Text, InfoBean>{ 32 private Text k = new Text(); 33 @Override 34 protected void reduce(InfoBean bean, Iterable<NullWritable> values,Reducer<InfoBean, NullWritable, Text, InfoBean>.Context context) 35 throws IOException, InterruptedException { 36 String account = bean.getAccount(); 37 k.set(account); 38 context.write(k, bean); 39 } 40 } 41 42 public static void main(String[] args) throws Exception { 43 Configuration conf = new Configuration(); 44 Job job = Job.getInstance(conf); 45 job.setJarByClass(SortStep.class); 46 47 job.setMapperClass(SortMapper.class); 48 //以下两行可以在满足一定条件的时候省略掉. 49 //在满足k2和k3,v2和v3一一对应的时候就可以省略掉. 看SumReducer类所在行的泛型. 50 job.setMapOutputKeyClass(InfoBean.class); 51 job.setMapOutputValueClass(NullWritable.class); 52 53 FileInputFormat.setInputPaths(job, new Path(args[0])); 54 55 job.setReducerClass(SortReducer.class); 56 job.setOutputKeyClass(Text.class); 57 job.setOutputValueClass(InfoBean.class); 58 FileOutputFormat.setOutputPath(job, new Path(args[1])); 59 job.waitForCompletion(true); 60 } 61 } 打成jar包,然后运行命令....输入为上面SumStep.java的输出 hadoop jar /root/itcastmr.jar itcastmr.SortStep /tradeout /trade_sort_out 排序之后的结果: 在MapReduce读取输入数据的时候,如果这个文件是以下划线开始的话,那么会不会读取这个文件中的内容...."_SUCCESS"文件就不会读取.... 如果想对某个类进行排序, 1.这个类要实现WritableComparable接口, 2.还要重写compareTo方法. 根据自己的业务逻辑自定义排序. 只需要把要排序的类当做k2 就可以了...框架自动排序. 要排序对象的compareTo方法是框架调用的,框架在shuffle这个阶段会调用排序. shuffle后面会讲,shuffle由很多很多的阶段组成,分区,排序,分组,combiner等等...把这些小的细节都讲完了之后再讲shuffle. 本文转自SummerChill博客园博客,原文链接:http://www.cnblogs.com/DreamDrive/p/7398455.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

信用借还之zhima.merchant.order.rent.query(信用借还订单查询)JAVA版本demo

说明: 接口作用:芝麻信用借还产品为商户提供的供商户查询借还订单详情的接口 附创建订单接口帖子:https://openclub.alipay.com/read.php?tid=3219&fid=72 调用示例代码如下: //zhima.merchant.order.rent.query 信用借还订单查询接口 public static void OrderRent_Query(){ AlipayClient alipayClient=alipayclient(); ZhimaMerchantOrderRentQueryRequest request = new ZhimaMerchantOrderRentQueryRequest(); reques

优秀的个人博客,低调大师

koubei.marketing.data.indicator.query(口碑商户经营数据查询接口)JAVA版本demo

说明: 经营报表产品是官方提供的一套标准接口,开发者通过此接口包可以获取商家的经营指标及商家会员的消费习惯洞察,同时接口支撑实时指标查询,口碑商户经营数据查询接口(koubei.marketing.data.indicator.query)可获取商户经营指标,包含会员发展、交易现状、活动评估。此接口支撑实时指标查询接口请求示例: //koubei.marketing.data.indicator.query(口碑商户经营数据查询接口)public static void DataIndicator_Query(){ AlipayClient alipayClient=alipayclient(); KoubeiMarketingDataIndicatorQueryRequest request =

优秀的个人博客,低调大师

koubei.marketing.data.trade.habbit.query(商户会员交易习惯查询接口)JAVA版本demo

说明: 商户会员交易习惯查询接口(koubei.marketing.data.trade.habbit.query)可获取会员在商户的消费习惯,包含复购率、桌单价、桌单价智能分析,商户会员交易习惯可帮助商户了解商户会员的消费习惯,以便更好的设置活动(如券门槛等)。接口请求示例: //koubei.marketing.data.trade.habbit.query(商户会员交易习惯查询接口) public static void DataTradeHabbit_Query(){ AlipayClient alipayClient=alipayclient(); KoubeiMarketingDataTradeHabbitQueryRequest request = ne

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册