-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathjava-array.clj
More file actions
208 lines (159 loc) · 6.35 KB
/
java-array.clj
File metadata and controls
208 lines (159 loc) · 6.35 KB
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
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
;; java collection
;; (load-file "java-array.clj")
;; first, import the java package.
(ns java-array
(:import [java.text SimpleDateFormat]
[java.util Calendar TimeZone])
(:use clojure.contrib.io
clojure.contrib.seq-utils)
;;
;; list logic operation, (and list1 list2)
(def data [[:x :e :e] [:o :x :e] [:o :e :x]])
(for [x [0 1 2]] (nth (nth data x) x)) ;; get diagonal
(for [x [0 1 2]] (nth (nth data x) (- 3 x))) ;; reverse diagonal
;; use java array as a mutable container for intermediate result.
here we are talking about JVM arrays: a mutable container
;; (alength tokens) (aget tokens 2) (aset tokens 2 "actionable")
;; split a string into java array
(def tokens (.split "clojure.in.action" "\\."))
;; use amap to prn array
(def z (amap tokens idx ret (aset ret idx (.concat "xx" (aget ret idx)))))
(amap z idx ret (prn (aget ret idx)))
(defn asum [#^floats xs]
(areduce xs i ret (float 0) (+ ret (aget xs i))))
(asum (float-array [1 2 3]))
;;
;; types of array : primitive and reference
;; primitive array : boolean-array byte-array char-array double-array float-array int-array long-array object-array short-array
;; use make-array and into-array functions to create primitive arrays:
(doto (StringBuilder. "abc")
(.append (char-array [\x \y \z])))
(let [ary (make-array Integer/TYPE 3 3)] ;; obtain Class objects for the primitive types
(dotimes [i 3]
(dotimes [j 3]
(aset ary i j (+ i j))))
(map seq ary))
(into-array Integer/TYPE [1 2 3])
;; reference array : Character [], array with boxed primitive.
;; into-array ret reference array of boxed primitive
(into-array ["a" "b" "c"])
(doto (StringBuilder. "abc")
(.append (into-array [\x \y \z])))
;=> #<StringBuilder abc[Ljava.lang.Character;@65efb4be>]
(into-array [(java.util.Date.) (java.sql.Time. 0)])
;; To create a heterogeneous array of java.lang.Object, use the to-array or to-array-2d
(to-array-2d [[1 2 3] [4 5 6]]) ;;=> #<Object[][] [[Ljava.lang.Object;@bdccedd>
(to-array ["a" 1M #(%) (proxy [Object] [])]) ;;=> #<Object[] [Ljava.lang.Object;@18987a33>
(to-array [1 (int 2)]) ;;=> #<Object[] [Ljava.lang.Object;@6ad3c65d>]]]]
;; variadic method/constructor calls
(String/format "An int %d and a String %s" (to-array [99, "luftballons"]))
;; clojure collections are map, set, sequential(list, vector)
;; clojure types are atom, array
;; Clojure object are boxed types.
;; JVM array are mutale. use aset to change ary content.
(def ary (into-array [1 2 3]))
(def sary (seq ary))
(aset ary 0 42)
;; Be cautious when sharing arrays from one function to the next, and especially across threads.
;; amap maps an expr across the ary.
(defn asum-sq [xs]
(let [dbl (amap xs i ret
(* (aget xs i)
(aget xs i)))]
(areduce dbl i ret 0
(+ ret (aget dbl i)))))
(asum-sq (float-array [1 2 3 4 5]))
;; sort a collection and convert back to vector for random access
;;
(defn sorted-vec
[coll]
(let [arr (into-array coll)]
(java.util.Arrays/sort arr)
(vec arr)))
;;
;; using forName to determine
(defmulti what-is class)
(defmethod what-is (Class/forName "[Ljava.lang.String;""]") [a] "1d String")
(defmethod what-is (Class/forName "[[Ljava.lang.Object;""]]") [a] "2d Object")
(defmethod what-is (Class/forName "[[[[I""]]]]") [a] "Primitive 4d int")
(defmethod what-is (Class/forName "[[D""]]") [a] "Primitive 2d double")
(defmethod what-is (Class/forName "[Lclojure.lang.PersistentVector;""]") [a])
;; use java util collections static methods, i.e., comparators, sort, etc.
(import '[java.util Comparator Collections ArrayList]')
(defn gimme [] (ArrayList. [1 3 4 8 2]))
(doto (gimme)
(Collections/sort (Collections/reverseOrder)))
(doto (gimme) (Collections/sort #(compare %2 %1)))
(doto (gimme) (Collections/sort >))
(doto (gimme) (Collections/sort <))
(doto (gimme) (Collections/sort (complement <)))
;; create a thread execute a runnable
(doto (Thread.
#(do (Thread/sleep 5000)
(println "haikeeba!")))
.start)
;; callable with future
;; FutureTask<V> ft = new FutureTask<V>(new Callable<V>(){public V call()});
;; how do we pass args ?
(import '[java.util.concurrent FutureTask]')
(let [f (FutureTask. #(do (Thread/sleep 5000) 42))]
(.start (Thread. #(.run f)))
(.get f)) ;; will block until done.
;; java.util.list conformance for sequence and seq.
;; no generic consideration due to erasure.
;; Clojure doesn't handle generics anyway type info does not exist at runtime.
(.get '[a b c] 1)
(.containsAll '[a b c] '[b c])
(.add '[a b c] 'd) ;; sequence not mutable
;; java.lang.comparable and comparator
;; vector is the only collection that impls Comparable IF.
;;
(.compareTo [:a] [:a])
(.compareTo [:a :b] [:a])
(.compareTo [:a :b] [:a :b :c])
(sort [[:a :b :c] [:a] [:a :b]])
;; java.util.Collection
;; idiom : use a Clojure sequence as a model to build a mutable sequence to use Java Collections API
(defn shuffle [coll]
(seq (doto (java.util.ArrayList. coll)
java.util.Collections/shuffle)))
(shuffle (range 10))
;; java.util.map, you can operate on JVM objects directly.
(doto (java.util.HashMap.) (.put :a "xxx"))
(java.util.Collections/unmodifiableMap
(doto (java.util.HashMap.) (.put :a 1)))
(into {} (doto (java.util.HashMap.) (.put :a 1)))
;;
;; When writing Clojure code, use errors to mean can’t continue and
;; exceptions to mean can or might continue.
;; Clojure's take on checked exception.
;; By default, declare that all functions throw the root Exception or RuntimeException.
;;
;; use clojure for data process
;;
;; parse a string with java.lang.String
(defn parse-line [line]
(let [tokens (.split (.toLowerCase line) " ")]
(map #(vector % 1) tokens)))
(parse-line "Twas brillig and the slithy toves")
;; combine a seq of key value pairs, group by reduce to a map.
(defn combine [mapped]
(->> (apply concat mapped)
(group-by first)
(map (fn [[k v]]
{k (map second v)}))
(apply merge-with conj)))
(use 'clojure.contrib.io')
(combine (map parse-line (read-lines "/Users/e51141/tmp/x")))
;; sum the tally count of a vec of value.
(defn sum [[k v]]
{k (apply + v)})
;; sum the val vector for each key, then merge keys
(defn reduce-parsed-lines [collected-values]
(apply merge (map sum collected-values)))
;; integrated solution
(defn word-frequency [filename]
(->> (read-lines filename)
(map parse-line)
(combine)
(reduce-parsed-lines)))