インタビュー中に多くの人がこのような問題に遭遇した可能性が
あります。1,000本の同じボトルがあり、そのうち999本は通常の水であり、そのうちの1本は非常に毒性が高く(希釈後も毒性があります)、小さなボトルは10本しかありません。白ネズミ、毒を飲んだ直後に死んでしまいますが、最短の時間でどの瓶が毒であるかを判断するためにそれらをどのように使用できますか?
コンピュータ言語では、すべての数値は最終的に計算のためにバイナリに変換され、バイナリの各「ビット」は数値0と1の2つの状態を表すことができることは誰もが知っています。
前の質問に戻ると、各マウスの生死の状態はバイナリシステムの「ビット」を表すことができます。10マウスは合計で1024の状態の組み合わせを表すことができます。したがって、この問題の解決策はこれらの1000本の水のボトルはバイナリ形式でマークされています(10桁ですべてをマークできます)。これらの10匹のマウスは10桁の1つに対応し、次に10桁の現在の桁に対応します。この位置に対応するマウス用に、上記1の水を混ぜて飲んでいますが、マウスの死に応じて、どのボトルの水が有毒かを特定することができます。
1. MeasureSpecからのビット操作を理解する
Android開発では、インプレースオペレーションも頻繁に見られます。ビューをカスタマイズする場合、int makeMeasureSpec(int size、int mode)メソッドを使用してビューのサイズと測定モードを取得します。2つの変数を1つにまとめる方法を教えてください。簡単に言うと、32ビットの2進数の上位2ビットは測定モードMeasureModeの格納に使用され、下位30ビットはサイズMeasureSizeの格納に使用されます。MeasureSpecはandroid.view.Viewクラスの内部クラスです。キーコードは次のとおりです。
public static class MeasureSpec {
private static final int MODE_SHIFT = 30;
//SpecMode 掩码,用于屏蔽高两位
//11 000000 00000000 00000000 00000000
private static final int MODE_MASK = 0x3 << MODE_SHIFT;
//00 000000 00000000 00000000 00000000
public static final int UNSPECIFIED = 0 << MODE_SHIFT;
//01 000000 00000000 00000000 00000000
public static final int EXACTLY = 1 << MODE_SHIFT;
//10 000000 00000000 00000000 00000000
public static final int AT_MOST = 2 << MODE_SHIFT;
//获取 MeasureSpec
public static int makeMeasureSpec(int size, int mode) {
// API 17 之前,忽略此条件
if (sUseBrokenMakeMeasureSpec) {
return size + mode;
} else {
return (size & ~MODE_MASK) | (mode & MODE_MASK);
}
}
//获取 SpecMode
public static int getMode(int measureSpec) {
return (measureSpec & MODE_MASK);
}
//获取 SpecSize
public static int getSize(int measureSpec) {
return (measureSpec & ~MODE_MASK);
}
}
ビット演算にはいくつかのタイプの演算子があり
ます。1.または演算子|:0 | 0 = 0、0 | 1 = 1、1 | 1 = 1
2.および演算子&:0&0 = 0、0&1 = 0、1&1 = 1
3.非演算子^:0 = 1、1 = 1
4.
MeasureSpecクラスの右シフト演算子>>および左シフト演算子<<:001 << 2 = 100,110 >> 1 = 11、 getModeメソッドは、パラメータmeasureSpecとMODE_MASKの間でAND演算を実行することです。MODE_MASKは、SpecModeのマスクとして理解できます。演算の結果は、measureSpecの上位2ビットを保持し、残りの30桁は0であり、結果はMeasureModeです。
getSizeメソッドは最初にMODE_MASKを逆にしてから、measureSpecとのAND演算を実行します。結果は定数値で、上位2ビットは0、下位30ビットはSpecSizeです。
makeMeasureSpecメソッドでは、サイズ&〜MODE_MASKの結果はサイズのSpecSizeであり、モード&MODE_MASKの結果はSpecModeです。これらのORをとると、結果は2つの値の重ね合わせ値になります。
第二に、実際の開発におけるビット演算の使用
同様に、日常の開発では、ビット演算を使用して一部の操作を簡略化することもできます。サーバーが数値を返す場合、重複するいくつかの状態が存在する可能性があります(次の図)。従来の方法に従って処理するのは非常に面倒です。 、今回はビット操作を使用する必要があります。
この複雑な状態を処理する新しいStatusManagerクラスを作成できます。
public class StatusManager {
// 正常
public static final int STATUS_NORMAL = 0 ; // 0000
//时间同步失败
public static final int STATUS_TIME_ASY = 1 ; // 0001
// 开门指令失败
public static final int STATUS_OPEN_DOOR = 1 << 1; // 0010
// 添加固定密码失败
public static final int STATUS_ADD_FIXED_PSW = 1 << 2; // 0100
// 删除固定密码失败
public static final int STATUS_DEL_FIXED_PSW = 1 << 3; // 1000
// 存储目前的权限状态
private int flag;
/**
* 重置状态
*/
public void setStatus(int status) {
flag = status;
}
/**
* 添加一种或者多种状态
*/
public void addStatus(int status) {
flag |= status;
}
/**
* 删除一种或者多种状态
*/
public void deleteStatus(int status) {
flag &= ~status;
}
/**
* 是否具有某些状态
*/
public boolean hasStatus(int status) {
return (flag & status) == status;
}
/**
* 是否不具有某些状态
*/
public boolean isHasnotStatus(int status) {
return (flag & status) == 0;
}
/**
* 是否仅仅具有某些状态
*/
public boolean isOnlyHas(int status) {
return flag == status;
}
}
状態を追加するとき、次のように書くことができます:
manager.addStatus(StatusManager.STATUS_TIME_ASY | STATUS_ADD_FIXED_PSW )
時刻同期とドアオープンコマンドが同時に失敗するかどうかを判断する必要がある場合は、次のように記述できます。
manager.hasStatus(StatusManager.STATUS_TIME_ASY | STATUS_OPEN_DOOR)
記事の最初に戻ってインタビューの質問を理解するのは簡単ですか?