Implement binary search for RandomAccessFileList, other API tweaks
This commit is contained in:
parent
8a50a0c9e6
commit
a8f5a83450
2
pom.xml
2
pom.xml
|
@ -4,7 +4,7 @@
|
|||
|
||||
<groupId>com.moparisthebest</groupId>
|
||||
<artifactId>filelists</artifactId>
|
||||
<version>0.0.1</version>
|
||||
<version>0.1-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>filelists</name>
|
||||
|
|
|
@ -5,6 +5,6 @@ package com.moparisthebest.filelist;
|
|||
*/
|
||||
public interface ByteArrayConverter<T> {
|
||||
int numBytes();
|
||||
T fromBytes(final byte[] buff);
|
||||
void toBytes(final T o, final byte[] buff);
|
||||
T fromBytes(final byte[] buff, final int off);
|
||||
void toBytes(final T o, final byte[] buff, final int off);
|
||||
}
|
||||
|
|
|
@ -16,20 +16,22 @@ public class LongConverter40Bit implements ByteArrayConverter<Long> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Long fromBytes(final byte[] buffer) {
|
||||
return (((long) buffer[4] & 0xFFL) << 32)
|
||||
| (((long) buffer[3] & 0xFFL) << 24)
|
||||
| (((long) buffer[2] & 0xFFL) << 16)
|
||||
| (((long) buffer[1] & 0xFFL) << 8)
|
||||
| ((long) buffer[0] & 0xFFL);
|
||||
public Long fromBytes(final byte[] buffer, int off) {
|
||||
off += 5;
|
||||
return (((long) buffer[--off] & 0xFFL) << 32)
|
||||
| (((long) buffer[--off] & 0xFFL) << 24)
|
||||
| (((long) buffer[--off] & 0xFFL) << 16)
|
||||
| (((long) buffer[--off] & 0xFFL) << 8)
|
||||
| ((long) buffer[--off] & 0xFFL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toBytes(final Long l, final byte[] buffer) {
|
||||
buffer[0] = (byte) ((l) & 0xFF);
|
||||
buffer[1] = (byte) ((l >> 8) & 0xFF);
|
||||
buffer[2] = (byte) ((l >> 16) & 0xFF);
|
||||
buffer[3] = (byte) ((l >> 24) & 0xFF);
|
||||
buffer[4] = (byte) ((l >> 32) & 0xFF);
|
||||
public void toBytes(final Long l, final byte[] buffer, int off) {
|
||||
--off;
|
||||
buffer[++off] = (byte) ((l) & 0xFF);
|
||||
buffer[++off] = (byte) ((l >> 8) & 0xFF);
|
||||
buffer[++off] = (byte) ((l >> 16) & 0xFF);
|
||||
buffer[++off] = (byte) ((l >> 24) & 0xFF);
|
||||
buffer[++off] = (byte) ((l >> 32) & 0xFF);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,53 +0,0 @@
|
|||
package com.moparisthebest.filelist;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by mopar on 2/9/17.
|
||||
*/
|
||||
public class Main {
|
||||
public static void main(String[] args) throws IOException {
|
||||
System.out.println("str " + new Date());
|
||||
//final List<Long> list = new RandomAccessFileList<>("/home/mopar/raf2.list", new UnsignedLongConverter(5));
|
||||
final List<Long> list = new RandomAccessFileList<>("/home/mopar/raf2.list", LongConverter40Bit.instance); list.clear();
|
||||
/*
|
||||
System.out.println(list.get(0));
|
||||
System.out.println(((RandomAccessFileList)list).longSize());
|
||||
System.out.println(((RandomAccessFileList)list).get(((RandomAccessFileList)list).longSize() - 1));
|
||||
*/
|
||||
//list.clear();
|
||||
/*
|
||||
long max = Integer.MAX_VALUE + 1000L;
|
||||
for(long l = 0; l < max; ++l)
|
||||
list.add(l);
|
||||
System.out.println("yay " + new Date());
|
||||
for(long l : list)
|
||||
System.out.println(l);
|
||||
*/
|
||||
//if(true) return;
|
||||
System.out.println(Integer.MAX_VALUE);
|
||||
System.out.println(list);
|
||||
list.add(5L);
|
||||
System.out.println(list);
|
||||
System.out.println(list.get(0));
|
||||
list.add(99999999999L);
|
||||
System.out.println(list.get(1));
|
||||
list.add(6L);
|
||||
list.add(4L);
|
||||
System.out.println(list);
|
||||
list.sort(Long::compareTo);
|
||||
System.out.println(list);
|
||||
System.out.println("------");
|
||||
//if(true) return;
|
||||
for(long l = 0; l < 1000; ++l)
|
||||
//for(long l = 7; l < 11; ++l)
|
||||
list.add(l);
|
||||
System.out.println(list);
|
||||
list.sort(Long::compareTo);
|
||||
list.sort(Comparator.reverseOrder());
|
||||
System.out.println(list);
|
||||
}
|
||||
}
|
|
@ -9,13 +9,14 @@ import java.util.*;
|
|||
/**
|
||||
* Created by mopar on 2/9/17.
|
||||
*/
|
||||
public class RandomAccessFileList<T> extends AbstractList<T> {
|
||||
public class RandomAccessFileList<T> extends AbstractList<T> implements AutoCloseable {
|
||||
|
||||
private final RandomAccessFile raf;
|
||||
private final byte[] buffer;
|
||||
private final ByteArrayConverter<T> bac;
|
||||
private final boolean close;
|
||||
|
||||
public RandomAccessFileList(final RandomAccessFile raf, final ByteArrayConverter<T> bac) {
|
||||
private RandomAccessFileList(final RandomAccessFile raf, final boolean close, final ByteArrayConverter<T> bac) {
|
||||
Objects.requireNonNull(raf);
|
||||
Objects.requireNonNull(bac);
|
||||
if (bac.numBytes() < 1)
|
||||
|
@ -23,14 +24,25 @@ public class RandomAccessFileList<T> extends AbstractList<T> {
|
|||
this.raf = raf;
|
||||
this.buffer = new byte[bac.numBytes()];
|
||||
this.bac = bac;
|
||||
this.close = close;
|
||||
}
|
||||
|
||||
public RandomAccessFileList(final RandomAccessFile raf, final ByteArrayConverter<T> bac) {
|
||||
this(raf, false, bac);
|
||||
}
|
||||
|
||||
public RandomAccessFileList(final String name, final ByteArrayConverter<T> bac) throws FileNotFoundException {
|
||||
this(new RandomAccessFile(name, "rw"), bac);
|
||||
this(new RandomAccessFile(name, "rw"), true, bac);
|
||||
}
|
||||
|
||||
public RandomAccessFileList(final File file, final ByteArrayConverter<T> bac) throws FileNotFoundException {
|
||||
this(new RandomAccessFile(file, "rw"), bac);
|
||||
this(new RandomAccessFile(file, "rw"), true, bac);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
if(close)
|
||||
raf.close();
|
||||
}
|
||||
|
||||
public T get(final int index) {
|
||||
|
@ -45,7 +57,7 @@ public class RandomAccessFileList<T> extends AbstractList<T> {
|
|||
raf.seek(index * buffer.length);
|
||||
if (raf.read(buffer) != buffer.length)
|
||||
throw new IOException("no full buffer to read, corrupted file?");
|
||||
return bac.fromBytes(buffer);
|
||||
return bac.fromBytes(buffer, 0);
|
||||
}
|
||||
|
||||
public int size() {
|
||||
|
@ -64,7 +76,7 @@ public class RandomAccessFileList<T> extends AbstractList<T> {
|
|||
public boolean add(final T o) {
|
||||
try {
|
||||
raf.seek(raf.length());
|
||||
bac.toBytes(o, buffer);
|
||||
bac.toBytes(o, buffer, 0);
|
||||
raf.write(buffer);
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
|
@ -84,7 +96,7 @@ public class RandomAccessFileList<T> extends AbstractList<T> {
|
|||
public T set(final long index, final T o) throws IOException {
|
||||
final T ret = get(index);
|
||||
raf.seek(index * buffer.length);
|
||||
bac.toBytes(o, buffer);
|
||||
bac.toBytes(o, buffer, 0);
|
||||
raf.write(buffer);
|
||||
return ret;
|
||||
}
|
||||
|
@ -98,6 +110,60 @@ public class RandomAccessFileList<T> extends AbstractList<T> {
|
|||
}
|
||||
}
|
||||
|
||||
public <K> long indexedBinarySearch(final K key, final TransformComparator<K, ? super T> c) throws IOException {
|
||||
long low = 0;
|
||||
long high = this.longSize()-1;
|
||||
|
||||
while (low <= high) {
|
||||
final long mid = (low + high) >>> 1;
|
||||
final T midVal = this.get(mid);
|
||||
final int cmp = c.compareTransform(key, midVal);
|
||||
|
||||
if (cmp > 0)
|
||||
low = mid + 1;
|
||||
else if (cmp < 0)
|
||||
high = mid - 1;
|
||||
else
|
||||
return mid; // key found
|
||||
}
|
||||
return -(low + 1); // key not found
|
||||
}
|
||||
|
||||
public <K> long iteratorBinarySearch(final K key, final TransformComparator<K, ? super T> c) throws IOException {
|
||||
long low = 0;
|
||||
long high = this.longSize()-1;
|
||||
ListIterator<? extends T> i = this.listIterator();
|
||||
|
||||
while (low <= high) {
|
||||
final long mid = (low + high) >>> 1;
|
||||
final T midVal = get(i, mid);
|
||||
final int cmp = c.compareTransform(key, midVal);
|
||||
|
||||
if (cmp > 0)
|
||||
low = mid + 1;
|
||||
else if (cmp < 0)
|
||||
high = mid - 1;
|
||||
else
|
||||
return mid; // key found
|
||||
}
|
||||
return -(low + 1); // key not found
|
||||
}
|
||||
|
||||
private T get(final ListIterator<? extends T> i, final long index) {
|
||||
T obj = null;
|
||||
int pos = i.nextIndex();
|
||||
if (pos <= index) {
|
||||
do {
|
||||
obj = i.next();
|
||||
} while (pos++ < index);
|
||||
} else {
|
||||
do {
|
||||
obj = i.previous();
|
||||
} while (--pos > index);
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sort(final Comparator<? super T> c) {
|
||||
try {
|
||||
|
|
|
@ -19,7 +19,7 @@ public class SignedLongConverter implements ByteArrayConverter<Long> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Long fromBytes(final byte[] buffer) {
|
||||
public Long fromBytes(final byte[] buffer, final int off) {
|
||||
/*
|
||||
if(true)
|
||||
return (((long)buffer[0] << 56) +
|
||||
|
@ -31,7 +31,7 @@ public class SignedLongConverter implements ByteArrayConverter<Long> {
|
|||
((buffer[6] & 255) << 8) +
|
||||
((buffer[7] & 255) << 0));
|
||||
*/
|
||||
int y = 0, x = (buffer.length * 8) - 8;
|
||||
int y = off, x = (this.numBytes * 8) - 8;
|
||||
if(debug) System.out.printf("l = (long)(buffer[%d] << %d);%n", y, x);
|
||||
long l = (long)(buffer[y] << x);
|
||||
x = x - 8;
|
||||
|
@ -40,7 +40,7 @@ public class SignedLongConverter implements ByteArrayConverter<Long> {
|
|||
if(debug) System.out.printf("l += ((long)(buffer[%d] & 255) << %d);%n", y, x);
|
||||
l += ((long)(buffer[y] & 255) << x);
|
||||
}
|
||||
for (; y < buffer.length; x = x - 8, ++y) {
|
||||
for (; y < this.numBytes; x = x - 8, ++y) {
|
||||
if(debug) System.out.printf("l += (buffer[%d] & 255) << %d;%n", y, x);
|
||||
l += (buffer[y] & 255) << x;
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ public class SignedLongConverter implements ByteArrayConverter<Long> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void toBytes(final Long l, final byte[] buffer) {
|
||||
public void toBytes(final Long l, final byte[] buffer, final int off) {
|
||||
/*
|
||||
writeBuffer[0] = (byte)(v >>> 56);
|
||||
writeBuffer[1] = (byte)(v >>> 48);
|
||||
|
@ -59,21 +59,21 @@ public class SignedLongConverter implements ByteArrayConverter<Long> {
|
|||
writeBuffer[6] = (byte)(v >>> 8);
|
||||
writeBuffer[7] = (byte)(v >>> 0);
|
||||
*/
|
||||
for(int y = 0, x = (buffer.length * 8) - 8; x > -1; x = x - 8, ++y) {
|
||||
for(int y = off, x = (this.numBytes * 8) - 8; x > -1; x = x - 8, ++y) {
|
||||
if(debug) System.out.printf("buffer[%d] = (byte) (l >>> %d);%n", y, x);
|
||||
buffer[y] = (byte) (l >>> x);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
final ByteArrayConverter<Long> bac = new SignedLongConverter(5);
|
||||
final byte[] buf = new byte[3]; // 5 99999999999L
|
||||
final ByteArrayConverter<Long> bac = new SignedLongConverter(buf.length);
|
||||
//System.out.println(4294967296L); System.out.println(Integer.MAX_VALUE * 2L); if(true)return;
|
||||
//System.out.println(Long.MIN_VALUE + 500);
|
||||
//bac.toBytes(99999999999L, buf); System.out.println(java.util.Arrays.toString(buf)); System.out.println(bac.fromBytes(buf)); if(true) return;
|
||||
for(long l = 0, c = 0; ; ++l) {
|
||||
bac.toBytes(l, buf);
|
||||
c = bac.fromBytes(buf);
|
||||
bac.toBytes(l, buf, 0);
|
||||
c = bac.fromBytes(buf, 0);
|
||||
if(l != c) {
|
||||
System.out.printf("limit for %d bytes l = %d c = %d%n", buf.length, l, c);
|
||||
return;
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
package com.moparisthebest.filelist;
|
||||
|
||||
/**
|
||||
* Created by mopar on 2/10/17.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface TransformComparator<K, T> {
|
||||
|
||||
int compareTransform(K o1, T o2);
|
||||
|
||||
}
|
|
@ -17,17 +17,17 @@ public class UnsignedLongConverter implements ByteArrayConverter<Long> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Long fromBytes(final byte[] buffer) {
|
||||
public Long fromBytes(final byte[] buffer, final int off) {
|
||||
long l = 0;
|
||||
for(int x = buffer.length - 1, y = (buffer.length * 8) - 8; x >= 0; --x, y = y - 8) {
|
||||
for(int x = this.numBytes - 1, y = (this.numBytes * 8) - 8; x >= off; --x, y = y - 8) {
|
||||
l |= (((long) buffer[x] & 0xFFL) << y);
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toBytes(final Long l, final byte[] buffer) {
|
||||
for(int x = 0, y = 0; x < buffer.length; ++x, y = y + 8) {
|
||||
public void toBytes(final Long l, final byte[] buffer, final int off) {
|
||||
for(int x = off, y = 0; x < this.numBytes; ++x, y = y + 8) {
|
||||
buffer[x] = (byte) ((l >> y) & 0xFF);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue