Hello guys,
I'm going to tell you about one of the negative aspects of Java on programming contests (actually, not only on contests), or, more precisely, how I have tried to resolve it. As you may know, Java has the disadvantage related to its collections library: the constraints of this language make you use object types even when using primitive types should be enough. Compare ArrayList<Integer>
and vector<int>
: Java list stores objects of type Integer, which are created every time when you add an element into the list (it's called boxing / unboxing), whereas C++ vector just stores ints. This behaviour slows down Java programs, and many people don't like it.
All this shit comes from the language design: you can't simply write a primitive type inside the angular brackets in Java. Some months ago I was thinking about this problem and came to the solution: why not just write my own collections library, with primitive types? Moreover, I haven't found any library with really all collections in the Internet.
That's how my small project EZ Collections (Github repository) was born. Of course, I haven't written all possible collections for all possible datatypes. Instead of that I have written each collection only once, leaving some hints for Maven plugin to generate everything as needed.
I have to say that this library is designed to use on programming contests or private purposes. It's thread-unsafe, it has some missing validations, it's prohibited to modify the collection during the iteration, it doesn't support serialization and maybe something else. But the problems on the contests can be solved without any troubles.
To use this library, you need:
Install Git and download the repository using
git clone
command (the URL is specified on the main page of the project). Or you can just download it using Download ZIP button.Download Maven (link to the download page), install and configure it (if you don't know anything about it — use Google, but, as far as I remember, it's enough just to set the path to Maven in the system variables).
Enter the root directory of the library and execute command
mvn clean install
. After that two jar files will appear in your local Maven repository, and also in the target folder. One of these jars contains class files, and the other one — source files. Now you can use them in your Java project.
But it's still unclear how to use it on contests. You need Egor's plugin CHelper for IntelliJ IDEA. After it had moved to Github, it became possible to merge the pull request that fixes some problems. The last pre-built version (commit 29dc20b), which includes my pull request, can be downloaded from here and installed in IDEA on your own.
After plugin update you can include the library into your contest project, specifying the path to the jar file with sources. That's all!
This is the example: let's solve the problem 118E - Bertown roads
- use
List<Integer>[]
for storing the graph: 8293080 — 1060 ms, 39100 KB - use
EzIntList[]
for storing the graph: 8293086 — 654 ms, 12148 KB
(this problem has quite large input, the larger it is, the more performance you gain)
One more example: solve the problem Timus 1521
With the TreeList's help the solution takes only a few lines:
int n = in.readInt();
int k = in.readInt();
EzIntList a = new EzIntTreeList(n);
for (int i = 0; i < n; i++) {
a.add(i);
}
int idx = 0;
for (int i = 0; i < n; i++) {
idx = (idx + k - 1) % a.size();
out.print(a.removeAt(idx) + 1);
out.print(' ');
}
What do we get using EZ Collections? For now, the following data structures are implemented:
- ArrayList
- ArrayDeque (with the possibility to get the element by its index)
- Heap
- Sort (guaranteed NlogN implementation)
- HashSet
- HashMap (I've used open addressing approach. I'm quite sure that it's not hackable)
- TreeSet
- TreeMap
- TreeList (the array that can perform add, set, insert and removeAt operations in logN time)
- Pair classes
Also I have to mention that there is famous Trove library (its repository can be found here) which has the similar idea, maybe some of you use it at work, but the problem is that only ArrayList, HashSet and HashMap are implemented in Trove. It's not enough for programming contests.
Some notes and plans:
NaN, POSITIVE_INFINITY and other similar stuff is not supported. You know who you are, if you use such things.
As it's impossible to return null (because EZ Collections store primitive types), method
returnedNull()
is added in every class where it's necessary. You must call it to perform null-check immediately after calling the method which could have returned null in usual Java Collections. For instance, these code fragments are identical:
TreeSet<Integer> set = new TreeSet<Integer>();
Integer lower = set.lower(42);
if (lower == null) {
...
}
EzIntTreeSet set = new EzIntTreeSet();
int lower = set.lower(42);
if (set.returnedNull()) {
// don't use the lower variable, it's not guaranteed that it has some certain value
}
The current source generation mechanism is ugly and doesn't support some cases that I want to support, so I'm planning to rewrite it. But all collections I wanted to implement in the first version already work.
boolean is considered to be uncomparable type, so Pairs with booleans don't implement Comparable. It will be fixed after rewriting the source generation.
Next collections I want to implement are LinkedList (on arrays). But it's only when I rewrite the source generation.
The next planned thing is to implement maps which have primitive key and object value types, or vice versa. It also should speedup programs a bit.
Please write any suggestions and feedbacks using the private messages on Codeforces.
Version history:
- Feb 21, 2015 — version 0.1.0 is released. It contains the identical content comparing to standard Java collections library.
- Mar 15, 2015 — version 0.1.1 is released. TreeList was added. Also the possibility to specify custom hash functions for HashSet/HashMap was added.
Good article ! Well Played ! :) gege :)